bash中何时发生分词?
我过去认为他们非常理解bash脚本,但最近有一件事让我对我的理解产生了疑问: 我认为单词分割是通过分割扫描输入,然后用空格替换bash中何时发生分词?,bash,Bash,我过去认为他们非常理解bash脚本,但最近有一件事让我对我的理解产生了疑问: 我认为单词分割是通过分割扫描输入,然后用空格替换IFS值中的任何内容来实现的 我打印了我的IFS,它是 >>> echo “$IFS” | xxd 00000000: 2009 0a0a 这告诉我,需要将所有制表符、换行符和空格转换为空格 因此,决定对其进行测试: list_of_stuff=("\n") for elm in "${list_of_stuff[@]}" do echo $
IFS
值中的任何内容来实现的
我打印了我的IFS,它是
>>> echo “$IFS” | xxd
00000000: 2009 0a0a
这告诉我,需要将所有制表符、换行符和空格转换为空格
因此,决定对其进行测试:
list_of_stuff=("\n")
for elm in "${list_of_stuff[@]}"
do
echo $elm
done
我希望它将\n
转换为\s
。但是,当我运行此命令时,会得到以下输出:
>>> sh test_bash_script.sh
>>>
…这告诉我它并没有像我预期的那样将
\n
转换为\s
。我应该在什么时候进行此转换?您的数组中没有换行符,它有一个反斜杠字符,后跟一个“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'
$ var2=$' \t \t \n \t ' # All whitespace this time
$ printf "'%s'\n" "$var2"
'
'
$ echo $var2
$ printargs $var2
Received 0 arguments:
让我们更详细地了解一下echo
和printargs
命令。在echo$var1
中,$var1
的值在空格(空格、制表符和换行符)上进行单词拆分,将其转换为三个单词:“word1”、“word2”和“word3”。这里没有空间,它们都被移除了。因此,它执行相当于echo“word1”、“word2”和“word3”
,echo
接受这三个参数,在它们之间添加空格,并打印结果
现在,我将printargs
定义为一个函数,用于打印它得到的参数数量,后跟每个参数(缩进和单引号)。因此,在printargs$var1
中,单词拆分也会发生同样的情况,因此它执行与printargs“word1”“word2”“word3”等价的,因此printargs
报告它有三个参数,并分别打印每个参数(没有空格,除了我为缩进添加的空格)
好的,接下来的一系列示例:
$ 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'
$ 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:
数组中没有换行符,它有一个反斜杠字符后跟一个“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'
$ var2=$' \t \t \n \t ' # All whitespace this time
$ printf "'%s'\n" "$var2"
'
'
$ echo $var2
$ printargs $var2
Received 0 arguments:
让我们更详细地了解一下echo
和printargs
命令。在echo$var1
中,$var1
的值在空格(空格、制表符和换行符)上进行单词拆分,将其转换为三个单词:“word1”、“word2”和“word3”。这里没有空间,它们都被移除了。因此,它执行与echo“word1”word2“word3”等价的echo
,接受这三个参数,在它们之间添加空格,并打印结果