IFS和命令替换
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了IFS和命令替换相关的知识,希望对你有一定的参考价值。
我正在编写一个shell脚本来读取输入csv文件并相应地运行一个java程序。
#!/usr/bin/ksh
CSV_FILE=$1
myScript="/usr/bin/java -version"
while read row
do
$myScript
IFS=$"|"
for column in $row
do
$myScript
done
done < $CSV_FILE
csv文件:
a|b|c
有趣的是,for循环之外的$ myScript可以工作,但for循环中的$ myScript说“/ usr / bin / java -version:找不到[没有这样的文件或目录]”。我知道这是因为我正在设置IFS。如果我评论IFS,并将csv文件更改为
a b c
有用 !我想shell使用默认的IFS来分隔命令/ usr / bin / java,然后再应用-version参数。由于我改变了IFS,它将整个字符串作为单个命令 - 或者我认为正在发生这种情况。
但这是我的要求:我有一个带有自定义分隔符的csv文件,该命令中包含参数,用空格分隔。我该怎么做才能正确?
IFS
表示如何在不带引号的替换中拆分变量的值。它适用于$row
和$myscript
。
如果你想使用IFS
进行拆分,这在普通的sh中很方便,那么你需要改变IFS
的值或者安排需要相同的值。在这种特殊情况下,通过将myScript
定义为myScript="/usr/bin/java|-version"
,您可以轻松地安排需要相同的值。或者,您可以及时更改IFS
的值。在这两种情况下,请注意,不带引号的替换不仅仅使用IFS
拆分值,它还将每个部分解释为通配符模式,并将其替换为匹配文件名列表(如果有)。这意味着,如果您的CSV文件包含类似的行
foo|*|bar
然后行不会是foo
,*
,bar
但foo
,当前目录中的每个文件名,bar
。要处理这样的数据,您需要使用set -f
关闭。还要记住,当一行以反斜杠结尾时,read
会读取延续行,并删除前导和尾随IFS
字符。使用IFS= read -r
关闭这两个行为。
myScript="/usr/bin/java -version"
set -f
while IFS= read -r row
do
$myScript
IFS='|'
for column in $row
do
IFS=' '
$myScript
done
done
然而,有更好的方法可以完全避免IFS分裂。不要将命令存储在以空格分隔的字符串中:它在复杂情况下失败,例如需要包含空格的参数的命令。存储命令有三种可靠的方法:
- 将命令存储在函数中。这是最自然的方法。运行命令是代码;你在函数中定义代码。您可以将函数的参数统称为
"$@"
。myScript () /usr/bin/java -version "$@" … myScript extra_argument_1 extra_argument_2
- 将可执行命令名及其参数存储在数组中。
myScript=(/usr/bin/java -version) … "$myScript[@]" extra_argument_1 extra_argument_2
- 存储一个shell命令,即shell要解析的东西。要评估字符串中的shell代码,请使用
eval
。一定要引用参数,就像任何其他变量扩展一样,以避免过早的通配符扩展。这种方法更复杂,因为它需要仔细引用。当您必须将命令存储在字符串中时,它才真正有用,例如,因为它作为脚本的参数出现。请注意,您不能以这种方式明智地传递额外的参数。myScript='/usr/bin/java -version' … eval "$myScript"
此外,由于您使用的是ksh而不是普通sh,因此您无需使用IFS
来分割输入行。使用read -A
代替直接拆分成数组。
#!/usr/bin/ksh
CSV_FILE=$1
myScript=(/usr/bin/java -version)
while IFS='|' read -r -A columns
do
"$myScript[@]"
for column in "$columns[@]"
do
"$myScript[@]"
done
done <"$CSV_FILE"
IFS
告诉shell哪些字符分隔“单词”,即命令的不同组成部分。所以当你从IFS
中删除空格字符并运行foo bar
时,脚本会看到一个参数“foo bar”而不是“foo”和“bar”。
最简单的灵魂是避免改变qazxsw poi并与qazxsw poi进行分裂,如下所示:
IFS
IFS应该放在“while”的后面
read -d <delimiter>
以上是关于IFS和命令替换的主要内容,如果未能解决你的问题,请参考以下文章