【问题标题】:Remove lines in text file which contain fewer than 4 pipes [closed]删除文本文件中包含少于 4 个管道的行 [关闭]
【发布时间】:2016-05-08 17:22:37
【问题描述】:

我有一个文本文件,其中的数据由 4 分隔 | 文件中有一些问题行。这些线路包含少于 4 个管道。 不需要问题行中的数据,我想在文件上运行一个命令,删除包含少于四个管道的任何行。我还想知道之后删除了多少行,所以如果在应用命令后可以将其打印在屏幕上,那将是理想的。

样本数据:

865|Blue Moon Club|Havana Project|34d|879
899|Soya Plates|Dimsby|78a|699
657|Sherlock
900|Forestry Commission|Eden Project|68d|864

期望的输出:

865|Blue Moon Club|Havana Project|34d|879
899|Soya Plates|Dimsby|78a|699
900|Forestry Commission|Eden Project|68d|864

我尝试了awk '|>=3' file.txt,但没有成功。有很多关于awk 的信息,其中一些是我找到的,但是由于其庞大的数量,所以很难找到我想要做的事情。

【问题讨论】:

标签: linux bash awk sed


【解决方案1】:

消除线条:

grep '|.*|.*|.*|' file > newfile

统计坏行数:

grep -cv '|.*|.*|.*|' file

这并没有进行适当的编辑;你可以使用sed 来做到这一点,但对新文件进行这样的编辑通常更安全,以免在出错时丢失数据。

第一个 grep 模式匹配任何带有四个管道符号的行。 (grep默认使用“Basic”正则表达式,你必须在其中编写交替运算符\|。所以你可以使用|作为一个普通字符。)

第二次调用计算 (-c) 不匹配 (-v) 行的数量。

这是一个简单的 sed 解决方案:

sed -n -i.bak  '/|.*|.*|.*|/p' file

-n 选项关闭自动打印,因此该命令仅打印与模式匹配的行。 (同样,默认情况下,sed 使用基本的正则表达式。)。 -i.bak 选项进行就地编辑,创建名称为 file.bak 的原始备份。

如果你想选择恰好四个管道的行,你可以使用awk

awk -F'|' 'NF==5' file > newfile

这会将字段分隔符设置为管道符号,然后选择正好有五个字段的行,即有四个管道的行。

一个有用的计算行数的工具是wc

wc -l file

会告诉你文件中有多少行;如果同时计算filenewfile 中的行数,差异显然是删除的数量。你也可以在 awk 中进行计算,但它有点冗长:

awk -F'|' 'NF==5{print;next}{del+=1}END{print del >>"/dev/stderr"}' file > newfile

【讨论】:

  • 在 awk 中打印到 stderr 的可移植方式是 awk '...END{print del | "cat>&2"}'
【解决方案2】:

这样就可以了:

sed -i.bak '/\([^|]*|\)\{4\}/!d' file

或者(如Cyrus's comment

sed -i.bak -E '/(\|[^\|]*){4}/!d' file

或者

sed -n '/^[^|]*|[^|]*|[^|]*|[^|]*|$/p' file > newfile

或者

sed -e '/^[^|]*|[^|]*|[^|]*|$/d' \
    -e '/^[^|]*|[^|]*|$/d' \
    -e '/^[^|]*|$/d' \
    -e '/^[^|]*$/d' \
    -i.bak file

但这不会给你行数。要获取行数,在原始文件上运行grep -cv '^[^|]*|[^|]*|[^|]*|[^|]*|$' file,如提到的rici,或使用wc -l file 命令比较前后的行号


解释:

前两个 sed 松散地匹配 4 个管道(不少于但可以更多),第三个恰好匹配 4 个 |(不多也不少)。

第四个sed 精确匹配 3、2、1 和 0 管道 (|) 并删除这些行(就地)并准备原始文件的备份文件 (file.bak)。

【讨论】:

  • 或使用 GNU sed:sed -E '/(\|[^\|]*){4}/!d' file
  • @Cyrus :我不确定像 ([ab]*)* 这样的正则表达式是否真的适用于 sed。感谢您指出。
猜你喜欢
  • 2019-06-26
  • 2021-12-06
  • 2014-11-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多