为什么使用 awk 可以正常工作,但如果我将变量分配给所述 awk 命令,它会破坏其中包含 space 的任何内容?

Why does using using awk work fine, but if i assign a variable to said awk command it breaks anything that has a space in it?

我正在制作一个读取 CSV 的脚本,我在其中放置了我想放在停靠栏上的各种图标的位置。如果我运行

awk -F "," '{print } test.csv

我会得到:

/Applications/Launchpad  
/Applications/Safari   
/Applications/Pages  
/Applications/Numbers  
/Applications/Keynote  
/Applications/Photos   
/Applications/iMovie  
/Applications/GarageBand  
/Applications/Microsoft\ Word  
/Applications/Microsoft\ Excel  
/Applications/Microsoft\ Powerpoint  

但是如果我将相同的命令分配给变量 this 和 运行

 for i in $this; do
     echo $i;

最后三行打印如下:

/Applications/Microsoft\  
Word  
/Applications/Microsoft\  
Excel  
/Applications/Microsoft\  
Powerpoint  

我知道它在 space 处明显坏了,需要修复它,但我不明白为什么它在一个中有效,但在另一个中无效。 强文本

默认情况下,Bash for 循环在所有空格处拆分,您可以通过在循环

之前设置 IFS=$'\n' 来覆盖它

测试结果:

akshay@db-3325:/tmp$ cat testfile 
/Applications/Launchpad  
/Applications/Safari   
/Applications/Pages  
/Applications/Numbers  
/Applications/Keynote  
/Applications/Photos   
/Applications/iMovie  
/Applications/GarageBand  
/Applications/Microsoft\ Word  
/Applications/Microsoft\ Excel  
/Applications/Microsoft\ Powerpoint  

假设您使用 awk 存储结果,如下所示

akshay@db-3325:/tmp$ testvar=$(awk '1' testfile)

默认行为

akshay@db-3325:/tmp$ for i in $testvar; do echo "$i"; done  
/Applications/Launchpad
/Applications/Safari
/Applications/Pages
/Applications/Numbers
/Applications/Keynote
/Applications/Photos
/Applications/iMovie
/Applications/GarageBand
/Applications/Microsoft\
Word
/Applications/Microsoft\
Excel
/Applications/Microsoft\
Powerpoint

这是 IFS

akshay@db-3325:/tmp$ IFS=$'\n';for i in $testvar; do echo "$i"; done; 
/Applications/Launchpad  
/Applications/Safari   
/Applications/Pages  
/Applications/Numbers  
/Applications/Keynote  
/Applications/Photos   
/Applications/iMovie  
/Applications/GarageBand  
/Applications/Microsoft\ Word  
/Applications/Microsoft\ Excel  
/Applications/Microsoft\ Powerpoint  

在您的代码中:

for i in $this; do
     echo $i;

$this 被扩展,然后被 Internal Field Separator ($IFS) 变量中的任何字符拆分,默认情况下是制表符、换行符和 space。为了获得您想要的行为,我们只希望字符串在换行符上拆分,因此我们使用以下方法将 IFS 设置为换行符:

IFS=$'\n'

应谨慎使用 IFS,建议将原始 IFS 值保存在另一个变量中,并在使用修改后的 IFS 后恢复它们。

或恢复原状:

IFS=$' \t\n'

总之:

IFS=$'\n'
for i in $this; do
     echo $i;
IFS=$' \t\n'

应该输出你想要的。

回答为什么会这样。 awk 输出不受 globbing 或拆分的影响,变量的扩展内容是。

要么

awk -F "," '{print } test.csv | while IFS= read -r line; do 
    do_stuff_with "$line"
done

或者完全跳过 awk

while IFS=, read -r first restOfList; do 
    do_stuff_with "$first"
done < test.csv

资源: