无论空格如何,完全读取每一行

时间:2013-11-09 23:21:33

标签: bash shell makefile

我的makefile的一部分如下:

list:          all
               for f in \
               `less fetch/list.txt`; \
               do \
                    echo $$f; \
                    ...
               done

fetch/list.txt包含文件列表:

path/file1.ml
path/file2.ml
path/file 3.ml
path/file 4.ml

问题是,即使文件名中允许空格,make list也会显示:

path/file1.ml
path/file2.ml
path/file
3.ml
path/file
4.ml

有没有人知道让每一行完整地读取,无论空格如何?

6 个答案:

答案 0 :(得分:5)

这是一种方法:

list:
        while IFS= read -r n ; do echo "line: $$n" ; done < list.txt

这是在行动:

$ cat list.txt 
abc
def
123 456

$ gmake
while read n ; do echo "line: $n" ; done < list.txt
line: abc
line: def
line: 123 456
line: 

答案 1 :(得分:1)

for files in
$(sed -n '/file/p' list.txt)
do
echo "${files}"
...
done

通常情况下,将命令绑定到循环的输出是错误的形式,但是sed通常可以可靠地执行,因为它总是引用整行。如果你希望它以与输入相同的形式输出,你必须确保在回显时在变量名周围加上双引号(“)。

答案 2 :(得分:1)

使用可能包含空格的变量时,必须引用它们以保留空格。这将起作用,例如:

for f in "$(cat fetch/list.txt)"; do     # preserve spacing from $()
    echo "$f"                            # preserve spacing from $f
done

另外几条建议:

  • 首选命令替换$(...)来反对`...`,因为它可以更好地使用引号和嵌套。
  • less是一个交互式命令,如果您只想要文件内容,请使用cat

但是直接循环文件内容会更有效(如Eric的回答中所述),而不是将文件转换为迭代的元素列表:

while read f; do           # read each line into f
    echo "$f"
done < fetch/list.txt      # from fetch/list.txt

在这里,read读取整行(而流程替换和反引号会生成项目列表,不一定是行,除非您引用它),因此在使用$f时只需要引号。请注意<输入重定向的位置:在done关键字之后,这可能看起来令人困惑。

答案 3 :(得分:1)

这可能对您有用:

for file in "$(<list.txt)"; do echo "$file"; done

答案 4 :(得分:0)

一种可能的解决方案是将fetch/list.txt提供给xargs,并为文件中的每一行执行命令:

xargs -i sh -c 'echo "${1}" ; ...' _ {} < fetch/list.txt

一般来说,在shell脚本中应谨慎处理for f in [some list of values that might contain spaces]

答案 5 :(得分:-1)

这似乎有效:

list:          all
    for f in "`cat filename`"; \
    do \
        echo "$$f"; \
    done

all:
    /bin/true