sed with while read 错过行

sed with while read 错过行

有人可以解释一下吗?

我有一个文件:

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,它将匹配当前语言环境中的任何数字和换行符。

还相关:

相关内容