【问题标题】:sed/awk conditionally delete lines from the start and end of a filesed/awk 有条件地从文件的开头和结尾删除行
【发布时间】:2020-11-22 16:38:21
【问题描述】:

我有几千个可能以

开头的文本文件
"

Start of text

但不是所有的换行符都相同,也不是所有的都有"

我想删除"(如果存在)和任何换行符(如果有)。

(还有结尾,但如果你告诉我如何从一开始就删除它,我可能会弄清楚)

End of file...

"

perl 也可以

我的尝试会是这样的鱼壳。 awk 可能性能更高

if head -1 | grep \"
    sed -i 1d $file
if head -1 | grep '^\r\n$'
    sed -i 1d $file
if head -1 | grep '^\r\n$'
    sed -i 1d $file
if head -1 | grep '^\r\n$'
    sed -i 1d $file

这可能真的有用,我要试试

【问题讨论】:

  • 您搜索了什么,找到了什么?您尝试过什么,它是如何失败的?
  • 更新了潜在的解决方案

标签: perl awk sed


【解决方案1】:

执行此操作的最简单方法是 2-pass 方法,在第一次通过时,您找出“好”行的开始和结束行号,然后在第二次打印这些数字之间的行:

awk '
    NR==FNR { if (NF && !/^"$/) { if (!beg) beg=NR; end=NR } next }
    (beg <= FNR) && (FNR <= end)
' file file

例如给定这个输入:

$ cat file
"

Start of text

but not all of them have the same number of line breaks and not all of them have "

I would like to remove " (if it exists) and any line breaks, if any.

(and the ending too but I'll probably figure it out if you show me how to remove it from the start)

End of file...

"

我们可以在每个 UNIX 机器上的任何 shell 中使用任何 awk 执行以下操作:

$ awk 'NR==FNR{if (NF && !/^"$/) {if (!beg) beg=NR; end=NR} next} (beg <= FNR) && (FNR <= end)' file file
Start of text

but not all of them have the same number of line breaks and not all of them have "

I would like to remove " (if it exists) and any line breaks, if any.

(and the ending too but I'll probably figure it out if you show me how to remove it from the start)

End of file...

【讨论】:

    【解决方案2】:

    除了两次处理之外,这里还有一次处理:

    awk '!/^"*$/{print b $0;f=1;b=""} f&&/^"*$/{b=b $0 ORS}' file
    

    程序由两个小部分组成:

    1. 只要有内容(包含超过" 的行),打印可能缓冲的行和当前输入行,设置内容已开始的标志,并清除缓冲区。

    2. 如果内容已经开始 (f),但当前行不包含任何内容,我们可能已经到了结尾,所以我们缓冲这些 行。稍后,(1) 将打印它们,否则它们将在 EOF 上被丢弃。

    【讨论】:

      【解决方案3】:

      您也可以使用ed 一次性完成:

      类似

      printf '%s\n' '1g/^"$/.,/^./-1d' '$g/^"$/?^.?+1,$d' w | ed -s "$file"
      

      翻译:如果第一行只是一个引号,d删除它和任何后面的空行。如果最后一行只是一个引号,则删除所有前面的空行和它。最后w将文件写回磁盘。

      【讨论】:

        【解决方案4】:

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

        sed '1{/^"$/d};/\S/!d;:a;${/^"$/Md};/\S/{n;ba};$d;N;ba' file
        

        如果包含单个",则删除第一行。

        删除文件开头的所有空行。

        为文件的其余部分形成一个循环。

        如果最后一行包含单个",则删除它。

        如果当前行不为空,打印它/它们,获取下一行并重复。

        如果当前行是最后一行且为空,请将其删除。

        当前行是空的,所以追加下一行并重复。

        注意这是一个单通道解决方案,允许在文件正文中使用空行。


        替代方案,内存密集型:

        sed -Ez 's/^"?\n+//;s/\n+("\n)?$/\n/' file
        

        【讨论】:

          猜你喜欢
          • 2019-12-01
          • 1970-01-01
          • 1970-01-01
          • 2023-03-05
          • 2015-10-17
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多