以下是用于读取框中存在的所有DSF的shell脚本。 但是由于该行有空格,所以显示在不同的行中。 对于那些不了解ioscan -m dsf
,用ls -ltr
replace它,然后输出结果是许可和名称显示在不同的行中,但我希望它们在同一行中。
#!/usr/bin/ksh for a in `ioscan -m dsf` do echo $a done
for
循环不是为循环遍历行而设计的。 for
循环遍历“单词”或“字段”。
循环行的惯用方式是结合使用while
循环和read
。
ioscan -m dsf | while read -r line do printf '%s\n' "$line" done
请注意,while循环由于管道而位于子外壳中。 在bash中你可以通过使用进程替换来解决这个问题。
while read -r line do printf '%s\n' "$line" done < <(ioscan -m dsf)
for循环将使用$IFS
(内部字段分隔符)变量中的字符作为分隔符来分隔值。 通常$IFS
包含一个空格,一个制表符和一个换行符。 这意味着for
循环将遍历“单词”,而不是循环。
如果你坚持使用for循环来遍历行,你必须将$IFS
的值更改为只换行。 但是,如果你这样做,你必须保存$IFS
的旧值,并在循环后恢复,因为许多其他的东西也依赖于$IFS
。
OLDIFS="$IFS" IFS=$'\n' # bash specific for line in $(ioscan -m dsf) do printf '%s\n' "$line" done IFS="$OLDIFS"
或者,您可以使用subshell来包含对$IFS
的更改:
( # changes to variables in the subshell stay in the subshell IFS=$'\n' for line in $(ioscan -m dsf) do printf '%s\n' "$line" done ) # $IFS is not changed outside of the subshell
也可以看看:
for l in $()
根据IFS执行分词:
$ for l in $(printf %b 'ab\nc'); do echo "$l"; done a b c $ IFS=$'\n'; for l in $(printf %b 'ab\nc'); do echo "$l"; done ab c
如果以后不使用,IFS不必被退回。
for l in $()
也执行路径名扩展:
$ printf %b 'a\n*\n' > file.txt $ IFS=$'\n' $ for l in $(<file.txt); do echo "$l"; done a file.txt $ set -f; for l in $(<file.txt); do echo "$l"; done; set +f a *
如果IFS=$'\n'
,换行符被剥离和折叠:
$ printf %b '\n\na\n\nb\n\n' > file.txt $ IFS=$'\n'; for l in $(<file.txt); do echo "$l"; done a b
$(cat file.txt)
(或$(<file.txt)
)也读取整个文件到内存。
没有-r反斜杠用于连续行并在其他字符之前移除:
$ cat file.txt \1\\2\ 3 $ cat file.txt | while read l; do echo "$l"; done 1\23 $ cat file.txt | while read -rl; do echo "$l"; done \1\\2\ 3
IFS中的字符从行的开头和结尾剥离,但未折叠:
$ printf %b '1 2 \n\t3\n' | while read -rl; do echo "$l"; done 1 2 3 $ printf %b ' 1 2 \n\t3\n' | while IFS= read -rl; do echo "$l"; done 1 2 3
如果最后一行不以换行符结尾,则读取赋给它,但在循环的主体之前退出:
$ printf 'x\ny' | while read l; do echo $l; done x $ printf 'x\ny' | while read l || [[ $l ]]; do echo $l; done x y
如果一个while循环处于管道中,它也在一个子shell中,所以变量在其外部是不可见的:
$ x=0; seq 3 | while read l; do let x+=l; done; echo $x 0 $ x=0; while read l; do let x+=l; done < <(seq 3); echo $x 6 $ x=0; x=8 | x=9; echo $x 0