Put*_*nik 0 bash newlines variable
我有一个文本文件(或管道输出,在这里无关紧要)
memcached.uptime 1061374
memcached.curr_connections 480
memcached.cmd_get 478962548
memcached.cmd_set 17641364
memcached.cmd_flush 0
Run Code Online (Sandbox Code Playgroud)
如果我使用命令,cat test.txt | while read i; do echo $i; done它会产生非常预期的输出:
memcached.uptime 1061374
memcached.curr_connections 480
memcached.cmd_get 478962548
etc
Run Code Online (Sandbox Code Playgroud)
但是如果我循环使用,for i in $(cat test.txt); do echo $i; done我会看到不同的东西:
memcached.uptime
1061374
memcached.curr_connections
480
memcached.cmd_get
478962548
etc
Run Code Online (Sandbox Code Playgroud)
问题是:为什么???
在:
cat test.txt | while read i; do echo $i; done
Run Code Online (Sandbox Code Playgroud)
您设法在许多 shell 脚本编写不良做法中进行了练习:
虽然我可能应该首先提到为什么使用 shell 循环来处理被认为是不好的做法的文本?.
尝试例如输入如下:
-n
/*/*/*/../../../*/*/*
foo\
bar
Run Code Online (Sandbox Code Playgroud)
如果您确实需要使用 shell 循环,那可能必须是这样的:
{
while IFS= read <&3 -r i; do
printf '%s\n' "$i" || exit
done
[ -z "$i" ] || printf %s "$i" || exit
} 3< test.txt
Run Code Online (Sandbox Code Playgroud)
在
for i in $(cat test.txt); do echo $i; done
Run Code Online (Sandbox Code Playgroud)
这用另一种代替了不好的做法。在这里,您有充分的理由不加$(cat test.txt)引号:您想要 split+glob 运算符的拆分部分,但您忘记指定要拆分的内容并禁用 glob 部分。
IFS='
' # split on newline only. The default value of $IFS
# contains space, tab and newline which explains why you see
# one word per line
set -o noglob # disable glob
for i in $(cat test.txt); do
printf '%s\n' "$i" || exit
done
Run Code Online (Sandbox Code Playgroud)
请注意,仍然会跳过空行,并且在开始循环之前读取文件内容并将其存储在内存中(多次)。