如何将工作 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/,然后再在这里提问。
我不熟悉 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/,然后再在这里提问。