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

时间:2017-03-15 22:07:08

标签: regex bash ksh

我不熟悉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

1 个答案:

答案 0 :(得分:3)

问题根本不是针对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 bash中=~右侧保证唯一支持的语法
  • 引用所有扩展。 echo "$x",而不是echo $x
  • 使用-r参数read,除非您明确要求它抑制的行为(除非配对,否则从输入中删除文字反斜杠,将其视为使read消耗多行(如果这样的反斜杠)是最后一个角色。)
  • 在调用IFS时清除read(因此,使用IFS= read),除非您明确要求修剪前导和尾随空格的行为; 如果您需要IFS来区分同时读取的多个字段之间的边界。

当使用ksh93和您提供的样本输入文件运行时,上述输出为:

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

(包括nobody:在输出中也是预期的,原因很明显,如果有人读取代码;在continue之后紧跟section=$x之后,在同一if内},如果 不受欢迎的话。)

将来,请在此处提问之前通过http://shellcheck.net/运行您的代码。