使用 awk 删除特定的无意换行符?

问题描述 投票:0回答:4

我有一个 10M 行的文件,其中包含我想要删除的虚假换行符。示例行是:

uno field, dos field, tres field, cuatro field, cinco field, seis field, siete field
one field, two field, three field, four
field, five field
ichi field, ni field, san field

我希望这个是:

uno field, dos field, tres field, cuatro field, cinco field, seis field, siete field
one field, two field, three field, four field, five field
ichi field, ni field, san field

我尝试使用 sed :

sed -z 's/four\n/four /g' input.txt

奇怪的是,sed 命令可以工作,但仅适用于使用

head -500000 input.txt
生成的文件的一小部分。似乎人们建议使用 awk 而不是 sed,但我不知道 awk,也无法组合正确的 awk 命令。有线索吗?

我正在尝试建立一个有效的过滤器。作为测试,我尝试过:

awk '/four\n/ {print}' input.text

但根本没有输出。

awk sed newline
4个回答
3
投票

奇怪的是,sed 命令有效,但仅适用于小子集

sed -z 's/four\n/four /g' input.txt
中,您已经使用了
-z
,其中
sed
手册
解释了以下方式

将输入视为一组行,每行以零字节终止( ASCII ‘NUL’ 字符)而不是换行符。

如果您的文件在任何地方都不包含

\000
字节,
sed
会将整个文件视为单行,如果不适合可用内存,则会导致失败。

awk '/four\n/ {print}' input.text

GNU AWK 默认在换行符处分割行,并且行不包含换行符,为了表示以

four
结尾的行,您应该写
/four$/
。我将使用 GNU AWK 来完成此任务,如下所示,让
input.txt
内容为

uno field, dos field, tres field, cuatro field, cinco field, seis field, siete field
one field, two field, three field, four
field, five field
ichi field, ni field, san field

然后

awk '{ORS=/four$/?" ":"\n";print}' input.txt

提供输出

uno field, dos field, tres field, cuatro field, cinco field, seis field, siete field
one field, two field, three field, four field, five field
ichi field, ni field, san field

说明:我使用所谓的三元运算符条件设置输出行分隔符

?
valueiftrue
:
valueiffalse如果行以
four
结尾则为空格,否则为换行符。如果您想了解更多有关
ORS
的信息,请阅读 8 强大的 Awk 内置变量 – FS、OFS、RS、ORS、NR、NF、FILENAME、FNR

(在 GNU Awk 5.1.0 中测试)

如果您严格限制使用 GNU

sed
并且最后一行 never
four
结尾,并且以 4 结尾的行是 never 相邻,那么可以按照以下方式完成

sed -e '/four$/N' -e 's/\n/ /' input.txt

说明:当行以四个 do N 命令结束时,即

向模式空间添加换行符,然后追加下一行输入 到模式空间。

然后使用空格替换换行符。

(在 GNU sed 4.8 中测试)


0
投票

如果你总是在“四”之后休息,你可以使用:

awk '/four$/ {printf "%s ", $0} !/four$/ {print}' input.txt
uno field, dos field, tres field, cuatro field, cinco field, seis field, siete field
one field, two field, three field, four field, five field
ichi field, ni field, san field

这能解决你的问题吗?


0
投票

这可能对你有用(GNU sed):

sed ':a;s/,/&/4;t;N;s/\n/ /;ta' file

如果一行包含 4 个或更多

,
,则不做进一步处理并打印它。

否则,追加下一行,用空格替换换行符,然后再继续。


0
投票

使用

-z
,您会受到可用内存的限制。此外,它不能移植到 GNU 之外的其他
sed
。并且
sed -z 's/four\n/four /g'
有一个额外的小缺陷:如果最后一行以
four
和换行符结尾,则该换行符将被替换为空格(可能不需要),这使得最后一行没有结束换行符(可能也是不需要的) ).

与任何符合 POSIX 标准的

sed

sed ':a;$!{/four$/{N;ba;};};s/\n/ /g' input.txt

这不会占用内存中的完整输入,并且即使有几行连续的行以

four
结尾,也能按预期工作。如果最后一行以
four
结尾,它也可以工作,在这种情况下,它不会在最后一行的末尾添加额外的空格并保留最后的换行符。

说明:

  • :a
    :声明循环标签
    a
  • $!{...}
    :在除最后一行之外的所有行上运行
    ...
    命令,
  • /four$/{N;ba;}
    :如果该行以
    four
    结尾,则将下一行追加到当前行,并用换行符分隔,然后分支到标签
    a
    ,
  • s/\n/ /g
    :用空格替换所有换行符。

注意:理论上这也受到可用内存的限制。如果您有数千个以

four
结尾的连续行,则循环会将它们连接在内存中,您可能会碰壁。

© www.soinside.com 2019 - 2024. All rights reserved.