我曾经认为很好地理解了bash脚本,但最近有些事情让我的理解受到质疑:
我认为单词拆分的工作原理是拆分扫描输入,然后用空格替换IFS
的值中的任何内容。
我打印了我的IFS,它是
>>> echo “$IFS” | xxd
00000000: 2009 0a0a
告诉我应该将所有制表符,换行符和空格转换为JUST空格。
所以,决定测试一下:
list_of_stuff=("\n")
for elm in "${list_of_stuff[@]}"
do
echo $elm
done
我希望它会将\n
转换为\s
。但是,当我运行它时,得到以下输出:
>>> sh test_bash_script.sh
>>>
..它告诉我它没有按照我的预期将\n
转换为\s
。我什么时候应该期待这种转换?
答案 0 :(得分:2)
你的数组中没有换行符,它有一个反斜杠字符后跟一个“n”。当shell执行echo $elm
时,它会将$elm
转换为'\ n',执行分词(找不到空白字符),并将其作为参数传递给echo
。 echo
然后会看到\n
,并执行转义解释(某些版本的echo
执行此操作,有些则不执行此操作)将其转换为换行符并打印出来。
尝试使用`printf''%s'\ n“$ elm来更好地了解正在发生的事情:
$ list_of_stuff=("\n")
$ for elm in "${list_of_stuff[@]}"; do
> printf "'%s'\n" $elm
> done
'\n'
$ list2=($'\n') # This'll give an actual newline
$ for elm in "${list2[@]}"; do
> printf "'%s'\n" $elm
> done
''
但是......为什么第二次没有打印出来?这是因为$elm
扩展为换行符,将单词拆分转换为0个单词,因此它运行相当于printf "'%s'\n"
,只打印两个单引号后跟换行符。
set -x
来更好地了解这种情况下发生了什么。在原始情况下,它会显示它正在执行相当于echo '\n'
。
[编辑]回答有关“变成0个单词”和等同于printf "'%s'\n"
的问题:单词拆分不会将任何东西变成空格;它将一个字符串变成一系列单词。如果echo
得到多个参数(“单词”),它会将它们粘在一起,中间有空格,因此单词拆分+ echo
可以将所有空格转换为单个空格,但实际上并不是什么单词分裂本身。考虑几个例子:
$ var1=$' \t word1 \n \t word2 \nword3 \n \n ' # Note that $' ' converts escape sequences
$ printf "'%s'\n" "$var1" # This prints the actual contents with quotes around, no further interpretation
' word1
word2
word3
'
$ echo $var1 # No quotes, so it gets word-split; echo pastes together with spaces
word1 word2 word3
$ printargs() { # Let's define a function to show what's happening more clearly
> echo "Received $# arguments:"
> for arg in "$@"; do
> printf " '%s'\n" "$arg"
> done
> }
$ printargs $var1
Received 3 arguments:
'word1'
'word2'
'word3'
让我们更详细地看一下echo
和printargs
命令。在echo $var1
中,$var1
的值在空格(空格,制表符和换行符)上进行分词,将其转换为三个词:“word1”,“word2”和“word3”。这里没有空格,它们都被删除了。所以它执行相当于echo "word1" "word2" "word3"
,echo
获取这三个参数,在它们之间添加空格,并打印结果。
现在,我将printargs
定义为一个函数,用于打印它获得的参数数量,后跟每个参数(缩进和单引号)。所以在printargs $var1
中,单词分裂发生的相同,所以它执行相当于printargs "word1" "word2" "word3"
,因此printargs
报告它有三个参数,并分别打印每个参数(没有空格,除了那些我为缩进添加的内容。)
好的,接下来的一系列例子:
$ var2=$' \t \t \n \t ' # All whitespace this time
$ printf "'%s'\n" "$var2"
'
'
$ echo $var2
$ printargs $var2
Received 0 arguments:
再次,让我们更详细地看一下最后两个命令:在echo $var2
中,分词在$var
的值中找到零个字 - 它都是空格 - 所以它传递零参数到echo
。该命令仅相当于echo
,完全没有参数。所以echo
只打印一个空行(没有空格或任何东西)。同样,在printf "'%s'\n" $var2
中,$var2
将单词拆分为零字,因此printargs
获取(并报告获取)零参数。将输出与这些完全等效的命令进行比较:
$ echo
$ printargs
Received 0 arguments: