有人可以解释一下吗?
我有一个文件:
cat listi.txt
sdfasdfsf123sadfasdf123
jlkjh2345ljkh245lkh4325
57hghf456ghf457gf467
这里 sed 错过了第一行:
while read line ; do sed 's/[^0-9]//g'; done < listi.txt
23452454325
57456457467
在这里看到:
while read line ; do echo $line; done < listi.txt
sdfasdfsf123sadfasdf123
jlkjh2345ljkh245lkh4325
57hghf456ghf457gf467
这可行,但感觉多余,我可能会错过它,因为我认为 sed 会传递所有行:
while read line ; do echo $line | sed 's/[^0-9]//g'; done < listi.txt
123123
23452454325
57456457467
为什么是这样?重新获得我对 bash 的信任,因为这让我产生怀疑
答案1
你的初始循环:
while read line; do
sed 's/[^0-9]//g'
done <listi.txt
这里发生的事情是read
从循环的输入流中读取一行,该输入流来自文件listi.txt
。该值存储到变量line
(有一些警告)并且不再使用。
sed
然后,在不提及输入文件的情况下完成调用,这意味着sed
将从其标准输入流中读取。
的标准输入流sed
是从循环继承的,因此它读取并处理第二行以及listi.txt
所有其他行,直到到达文件末尾。
然后循环read
再次执行,但由于没有更多内容可读取,因此调用失败并且循环终止。
listi.txt
上面的总体效果是忽略文件的第一行,同时sed
从第二行开始处理文件,从每行中删除非数字并将它们输出到终端。
如果您只想将sed
表达式应用于 中的所有行listi.txt
,您可以使用
sed 's/[^0-9]//g' listi.txt
也就是说,不需要使用单独的 shell 循环,因为sed
默认情况下会将其编辑表达式应用于输入文件中的每一行。
如果您想要删除所有非数字,那么您也可以使用 来执行此操作tr
,这是一个执行单个字符转换的工具:
tr -d -c '0-9\n' <listi.txt
这-d
将从输入中删除 ( ) 属于-c
上述字符集的补码 ( ) 一部分的任何字符(0-9\n
;我们可能希望保留将输入分为几行的换行符,这就是此处包含的原因)。该0-9\n
位也可以写成[:digit:]\n
,它将匹配当前语言环境中的任何数字和换行符。
还相关: