【问题标题】:How to convert working bash script to ksh script如何将工作 bash 脚本转换为 ksh 脚本
【发布时间】:2017-03-15 22:07:08
【问题描述】:

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

【问题讨论】:

  • 不要对多行代码段使用反引号;它们仅适用于少于一行的 sn-ps。
  • 顺便说一句,[[ $string =~ $re ]] 实际上在 ksh 中完全合法。另一方面,\S 是 PCRE 扩展,不保证在 ERE 中工作(因此,不保证在 bash 中工作)。
  • 好吧,在适当的 David Korn ksh93 中完全合法。有许多不同版本的 ksh(不要让我开始研究大量糟糕、缓慢、不兼容的克隆)。指定确切的 shell 和版本会很有帮助。
  • 顺便说一句,“我需要有人为我做 X”通常不是一个好的 StackOverflow 问题。我们在这里帮助您解决在尝试自己编写代码时遇到的问题,而不是代表您构建解决方案。
  • 要清楚,顺便说一句,[[ $x == '^\S+:' ]] 在 bash 中也是无效的——从来没有工作过的级别无效;它检查你的字符串是否完全是^\S+:not检查你的字符串是否匹配正则表达式。

标签: regex bash ksh


【解决方案1】:

这些问题根本不是 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 消耗多行)。
  • 在调用read 时清除IFS(因此,使用IFS= read),除非您明确想要修剪前导和尾随空格的行为; 如果您需要使用IFS 来区分同时读取的多个字段之间的边界。

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

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

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-06-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-19
    • 2022-06-15
    • 2016-01-29
    • 1970-01-01
    相关资源
    最近更新 更多