希望这个问题以前没有出现过。至少我没有找到答案。也许看起来不太好:(
假设我得到了这段文字:
hello "hello" "hello world"
请告诉我为什么这两个脚本有不同的输出?:
1) 文本保存在文件中
#!/bin/bash
while read line
do
set $line
echo $1
echo $2
echo $3
done < "file"
输出是:
hello
"hello"
"hello
2) 在脚本中硬编码的文本
#!/bin/bash
set hello "hello" "hello world"
echo $1
echo $2
echo $3
这是输出:
hello
hello
hello world
我想在从不同文件读取行时获得第二个行为。请堆垛机帮忙:(
最佳答案
这是一个shell命令:
set hello "hello" "hello world"
因为它是一个 shell 命令,所以 shell 在执行命令之前执行引号删除作为最后一步。
将其与文件中的文本进行对比:
$ cat file
hello "hello" "hello world"
当 shell 读取这个文件时,它把引号当作另一个字符。此文件中的引号从不直接出现在命令行中,因此它们不会被引号删除。
文档
摘自 man bash
中讨论扩展的部分:
Quote Removal
After the preceding expansions, all unquoted occurrences of the characters \, ', and " that did not result from one of the above expansions are removed.
分词和删除引号如何相互作用
Bash 在删除引号之前进行分词。这很重要,例如,对于此命令:
set hello "hello" "hello world"
当 shell 进行单词拆分时,它会找到 set
命令的三个参数。只有在执行 set
之前的最后一步,shell 才会删除引号。由于没有进行进一步的单词拆分,因此 set
的参数数量仍为三个。
让我们将上面的内容与从文件中读取一行的结果进行对比:
$ cat file
hello "hello" "hello world"
$ read line <file
$ echo "$line"
hello "hello" "hello world"
如上所述,shell 不会删除 line
的内容的引号。现在,让我们使用 $line
作为 set
的参数:
$ set $line
$ echo $#
4
找到四个参数。这些参数是:
$ echo 1=$1 2=$2 3=$3 4=$4
1=hello 2="hello" 3="hello 4=world"
如您所见,文件中的引号被视为普通字符,例如 h
或 e
。因此,文件中的 "hello world"
被扩展为两个词,每个词都有一个引号字符。
关于linux - Bash 将带引号的行拆分为参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39233860/