2011-05-16 12:14:48 +0000 2011-05-16 12:14:48 +0000
247
247

Bash: 在变量中迭代行

如何在bash中正确地迭代变量中的行,或者从命令的输出中迭代行?简单地将IFS变量设置为新的行,对于命令的输出是有效的,但是当处理一个包含新行的变量时,就不行。但是,第一个for循环打印出的是单行的所有项目。有什么想法吗?

答案 (5)

312
312
312
2011-05-16 13:47:36 +0000

使用bash,如果你想在一个字符串中嵌入新的行,可以用$''括起来:

$ list="One\ntwo\nthree\nfour"
$ echo "$list"
One\ntwo\nthree\nfour
$ list=$'One\ntwo\nthree\nfour'
$ echo "$list"
One
two
three
four

如果你已经在一个变量中包含了这样一个字符串,你可以用

while IFS= read -r line; do
    echo "... $line ..."
done <<< "$list"
```逐行读取它:

&001
72
72
72
2011-05-16 12:21:28 +0000

你可以使用while+read

some_command | while read line ; do
   echo === $line ===
done

。如果你想要便携性,请用-e代替。

32
32
32
2014-03-17 21:45:33 +0000
#!/bin/sh

items="
one two three four
hello world
this should work just fine
"

IFS='
'
count=0
for item in $items
do
  count=$((count+1))
  echo $count $item
done
15
15
15
2011-05-16 12:45:14 +0000

下面是一个有趣的for循环的方法:

for item in ${list//\n/
}
do
   echo "Item: $item"
done

。它包含了$line后面的`下面是一个有趣的for循环的方法:

for item in ${list//\n/
}
do
   echo "Item: $item"
done

。它包含了$line后面的的实例。你可以清楚的看到:

cr='
'
for item in ${list//\n/$cr}
do
   echo "Item: $item"
done

替换是用空格来代替这些,这就足够让它在循环中工作了:

for item in ${list//\n/ }
do
   echo "Item: $item"
done

演示:

$ cat t.sh
#! /bin/bash
list="One\ntwo\nthree\nfour"
echo $list | hexdump -C

$ ./t.sh
00000000 4f 6e 65 5c 6e 74 77 6f 5c 6e 74 68 72 65 65 5c |One\ntwo\nthree\|
00000010 6e 66 6f 75 72 0a |nfour.|
00000016
3
3
3
2019-05-07 16:19:00 +0000

你也可以先将变量转换为数组,然后迭代。

lines="abc
def
ghi"

declare -a theArray

while read -r line
do
    theArray+=($line)            
done <<< "$lines"

for line in "${theArray[@]}"
do
    echo "$line"
    #Do something complex here that would break your read loop
done
``` &001 


这只有在你不想乱用`IFS`和`read`命令的情况下才有用,因为如果你在循环中调用另一个脚本,在返回之前,该脚本可能会清空你的读取缓冲区,就像我遇到的那样。