对于循环读取单词而不是bash中的行

时间:2019-06-13 18:22:54

标签: bash grep

我在看似简单的脚本时遇到了问题。

基本上看起来像这样:

for s in $(cat FILENAME| grep User)
do
echo "$s"

done

但是没有给我类似结果:

User bla bla bla
User2 something blabla

结果就是:

User
bla
bla
bla
User2

2 个答案:

答案 0 :(得分:0)

catgrep产生的行恰巧包含空格。 for构造是从每一段而不是每一行中赚取美元。

根据显示的内容,您可以简单地使用catgrep,而不必担心循环。

答案 1 :(得分:0)

就像@donjuedo statet一样,通常将空格视为分隔符,这就是为什么您看不到整行的原因。有几种方法可以解决此问题。 我列出了从文件读取和从命令输出读取的解决方案。作为输入,您可以创建一个具有以下内容的文件,并将其命名为testfile.txt(带有空行,行之间以及两端都有空格的行:

This is the first line
2
third line

fifth line 
 sixth line   

解决方案1:最普遍适用

while IFS= read -u 3 -r line; do
    echo ">${line}<"
    read -p "press enter to show next line" var
    echo "read caught the following input: >$var<"
done 3< testfile.txt

从管道读取的变量看起来完全一样,只是最后一行发生了变化。作为示例,我处理了测试文件中所有包含空格的行,从而消除了第二行和第四行(这里用<&3代替-u 3-两者都是等效的):

while IFS= read -r line <&3;  do
   ...
done 3< <(grep " " testfile.txt)

这适用于大型输入文件。 3 <间接似乎很尴尬,但是请确保循环内的进程仍可以从标准输入中读取(请参阅读取语句“ press enter ...”)。如果执行的命令可能会显示用户提示自己(例如rm等),这可能很重要。 所以:

  • 也适用于大型输入文件,而不会消耗内存

  • stdin不会重定向(而是使用fd 3)

  • (使用IFS)保留位于谎言两端的
  • 空间,

  • 空行保留得很好

感谢@BenjaminW提出这个建议。

解决方案2:使用IFS和for(有限制)

OFS="$IFS"
IFS=$'\n'
for line in $(cat testfile.txt) ; do
  echo ">${line}<"
  read -p "press enter to show next line" var
  echo "read caught the following input: >$var<"
done
IFS="$OFS"

这会暂时将字段分隔符更改为换行符,因此仅在换行符处拆分文件。

  • 不建议用于大型输入,因为命令行替换($(cat testfile))

  • stdin也未重定向,因此可以在体内使用stdin而无需限制

  • (使用IFS)保留位于谎言两端的
  • 空间,

  • 作为第四行的空行在这里被跳过(行长0 /匹配^ $)

  • 如果使用此功能,则必须确保重置IFS

  • 如果您的循环主体需要对字段进行不同的解释(例如,需要读取其他应在空格周围分割的内容),则可能会变得混乱。