如何将工作 bash 脚本转换为 ksh 脚本

How to convert working bash script to ksh script

我不熟悉 ksh 脚本,我想将其转换为可用的 ksh 脚本。

egrep "^[^#;]" /etc/security/user | 
while read x; 
do 
if [[ $x == '^\S+:' ]]; then 
section=$x; 
fi; 
if [[ $section == 'nobody:' ]]; then 
echo $x; 
fi; 
done

/etc/security/user内容如下:

sys:
        admin = true
        expires = 0101000070
        login = false
        rlogin = false
adm:
        admin = true
        login = false
        rlogin = false
nobody:
        admin = true
        expires = 0101000070
        login = false
        rlogin = false
invscout:
        admin = true

我的目标是能够指定我想从哪个用户获取参数并让它只回显该用户的参数。例如,如果我在命令中指定 "nobody",shell 应该输出:

    admin = true
    expires = 0101000070
    login = false
    rlogin = false

我知道 ksh 不支持与 bash 相同的模式匹配正则表达式,但我无法成功转换命令。任何和所有帮助将不胜感激。不带空格的命令如下:

grep "^[^#;]" /etc/security/user | while read x; do if [[ $x =~ '^\S+:' ]]; then section=$x; fi; if [[ $section == 'nobody' ]]; then echo $x; fi; done

这些问题根本不是 ksh 特有的。以下在 ksh(版本 93u+ 2012-08-01)中是完全合法的,并且是 也是 bash 中的最佳实践代码(或至少接近它;有人可能将 grep 移动到进程替换中作为增强功能,这将在两个 shell 中增加价值。

#!/usr/bin/env ksh
section_re='^[^[:space:]]+:'
grep -v '^[#;]' /etc/security/user |
  while IFS= read -r x; do
    if [[ $x =~ $section_re ]]; then
      section=$x
    fi
    if [[ $section = 'nobody:' ]]; then
      echo "$x"
    fi
  done
  • == 不是用于字符串比较的 test 的 POSIX 标准化参数。使用 = 代替,即使在非 POSIX shell 上,以确保良好的习惯(这将转移到 POSIX 平台)。
  • === 不执行正则表达式测试;运算符是 =~.
  • =~ 的右侧参数必须不加引号 以防止它被视为文字。将正则表达式放在一个变量中,并在不加引号的情况下扩展该变量,是执行此操作的最佳实践可移植机制。
  • \S 在 POSIX 扩展正则表达式中无效,它是 ksh [=44] 中 =~ 右侧唯一保证支持的语法=]或 bash.
  • 引用所有扩展。 echo "$x",不是 echo $x
  • 使用 read-r 参数,除非您明确想要它抑制的行为(除非配对,否则从输入中删除文字反斜杠,如果这样的话,将它们视为使 read 消耗多行反斜杠是最后一个字符)。
  • 在调用 read 时清除 IFS(因此,使用 IFS= read),除非您明确想要修剪前导和尾随空格的行为; 如果你需要IFS来区分同时读取的多个字段之间的边界。

上面的输出,当 运行 使用 ksh93 和您提供的示例输入文件时,是:

nobody:
        admin = true
        expires = 0101000070
        login = false
        rlogin = false

(在输出中包含 nobody: 也是预期的,原因如果阅读代码就很明显;在 section=$x 之后紧跟一个 continue,在同一个 if,如果 那是 不需要的)。

以后,请先运行你的代码http://shellcheck.net/,然后再在这里提问。