我想将任何行输入到我的脚本中,并“按原样”对待它,就像单个参数一样,不按空格或任何内容分割,不删除双空格。例子:
# op.sh
IFS=$'\n'
echo "$*"
./op.sh one two three
one
two
three
# Desired output
./op.sh one two three
one two three
所以它会读取直到换行(输入)。
答案1
程序(脚本、应用程序等)看不到调用它的命令行。它得到一系列由调用 shell 解析的零个或多个参数。
例如,当您运行时,处理的ls f*
不是,而是 shell。如果您有三个以 f 开头的文件,那么shell 可能会将其解析为,并且执行的就是这个。在这种情况下,看到这三个论点,而不是ls
f*
ls f*
ls final food fred
ls
f*
类似地,当您执行./op.sh one two three
shell 时,会将其解析为./op.sh
三个空格分隔的参数one
、two
和three
。作为解析的一部分,空白被丢弃。你可以用这样的脚本看到这一点
#!/bin/bash
for a in $*; do echo "Found * argument ($a)"; done
echo
for a in "$@"; do echo "Found @ argument ($a)"; done
echo
echo "All together, they are ($*)"
如果它被调用,args
您可以使其可执行(chmod a+x args
),然后像这样调用它
./args one two three
相应的输出是
Found * argument (one)
Found * argument (two)
Found * argument (three)
Found @ argument (one)
Found @ argument (two)
Found @ argument (three)
All together, they are (one two three)
如果您对此进行试验,您可能会注意到$*
代表命令行参数,每个参数都用一个空格分隔,而且内部空格也再次分隔开。这通常没有用。相反,请使用双引号"$@"
,这可以进一步防止无意中解析参数。但无论哪种方式,参数都是根据解析的参数重建的,而不是原始命令行的副本。
为了保持空白完整,您必须引用该字符串。双引号允许$(...)
扩展变量和结构。单引号留给你一个文字。这里我使用单引号
引用空格
./args 'one two three'
Found * argument (one)
Found * argument (two)
Found * argument (three)
Found @ argument (one two three)
All together, they are (one two three)
单引号
'one more $HOME to go'
Found * argument (one)
Found * argument (more)
Found * argument ($HOME)
Found * argument (to)
Found * argument (go)
Found @ argument (one more $HOME to go)
All together, they are (one more $HOME to go)
双引号
./args "one more $HOME to go"
Found * argument (one)
Found * argument (more)
Found * argument (/home/roaima)
Found * argument (to)
Found * argument (go)
Found @ argument (one more /home/roaima to go)
All together, they are (one more /home/roaima to go)
答案2
这种类型的拆分与 IFS 无关。
这是将一行转换为单词的最基本的拆分。
单词是 shell 可以执行操作的单个标记。就像阅读一个句子一样,首先要把它分成单词,然后理解单词的含义。
避免这种分裂的唯一方法是引用。这就是引用被发明的根本原因。
$ op.sh () { printf '%s\n' "$@"; }
$ op.sh one two three
one
two
three
$ op.sh "one two three"
one two three
它不再有魔力了。