【问题标题】:search pattern and delete the next line after pattern from 2nd occurrence using SED使用 SED 搜索模式并从第二次出现的模式后删除下一行
【发布时间】:2014-12-20 06:39:51
【问题描述】:

我是 Shell 脚本的新手,需要您的帮助以找到一种“使用 SED 搜索模式并从第二次出现的模式中删除模式之后的下一行”的方法。我能够在搜索模式(第一次出现)之后删除该行,但我的要求需要在第二次出现后删除空行。

sed -re "s/^([^^L])/ \1/" -e "s/^^L/1/" -e "/$esc_filename/{p;s/$esc_filename/"${new_filename}"/}" -e "/^"$new_filename"/{n;d}" "$i" >> "$source_dir/${cap_new_rep_id}.TXT"

sed -re "s/^([^^L])/ \1/" -e "s/^^L/1/" -e "/^ $esc_filename/{p;s/$esc_filename .*/"${cap_new_rep_id}"/}" -e "/"${cap_new_rep_id}"/{N;s/\n.*//;}" "$i" >> "$source_dir/${cap_new_rep_id}.TXT"

上面的命令确实搜索 Control-L 并且如果找到用 1 替换 else 一个空格,然后再次搜索一个字符串并替换为另一个字符串,最后将搜索最新的字符串并删除之后的下一行但是我只需要在找到第二个模式后删除下一行的选项。

如果有人能够为实现这一目标提供一些启示,那就太好了。

感谢您的帮助。

【问题讨论】:

  • 向我们提供了要更改的文本的输出以及您期望的输出。

标签: sed


【解决方案1】:

考虑改用awk

awk -v first=1 '
  !ignore { print }           # unless the line is ignored, print it
  ignore { ignore = 0 }       # if it was ignored, reset ignore flag
  /pattern/ {
    if(!first) { ignore = 1 } # set ignore bit it pattern is found and it is not the first time
    first = 0                 # since the pattern has been found, it is not the first time after this.
  }' foo.txt

转换这个文件:

 0
 pattern
 1
 2
 3
 pattern
 4
 pattern
 6
 7

进入这个:

0
pattern
1
2
3
pattern
pattern
7

只需将模式替换为您的模式,就可以了。此外,与使用 sed 相比,查看正在发生的事情要容易得多。

编辑:我不应该尝试在带有单引号的 shell 脚本字符串中的 cmets 中使用 '。太傻了。

附录:由于 OP 在 cmets 中询问,除了第一次出现模式之外,删除第 N 行的一种方法是使用忽略计数器而不是标志:

# adjust N as necessary
awk -v first=1 -v ignore=0 -v N=2 '
  ignore != 1 { print }          
  ignore != 0 { ignore -= 1 }
  /pattern/ {
    if(!first) { ignore = N }
    first = 0                
  }' foo.txt

...我相信这就是我留下指向awk tutorial 的链接的地方。

【讨论】:

  • 非常感谢您的快速周转。我请求 SED 命令的原因是我不想再次读取输出文件并应用 AWK,而是使用 SED 命令一次性完成。相信你明白。
  • 您可以像使用 sed 一样通过 awk 进行管道传输。只是不指定文件名,它将从标准输入读取。
  • 感谢 Winter,我已经完成了我发布此请求的任务。我修改了我的脚本并用管道添加了 AWK 并将其写回输出文件。修改后的脚本:=============== sed -re "s/^([^^L])/ \1/" -e "s/^^L/1/" - e "/^ $esc_filename/{p;s/$esc_filename .*/"${cap_new_rep_id}"/}" "$i" | awk -v first=1 "!ignore { print } ignore { ignore = 0 } /"$cap_new_rep_id"/ { if(!first) { ignore = 1 } first = 0 }" >> "$source_dir/${cap_new_rep_id} .TXT"
  • 嗨,冬天,除了下一行或第一行之外,还有删除第二行或第三行的选项吗?
  • 当然。添加了示例和重要链接。
【解决方案2】:
sed '0,/pattern/!{/pattern/{N
s/\n.*//g}}'

示例包含以下内容的文件

hello world
I DON'T want to delete this line since the first pattern is above
world
I want to delete this line
my name is John
my name is Joe
world
I want to delete this line
My name is Jack
this is world
I want to delete this line
rule

在这种情况下,让我们考虑模式是world

   sed '0,/world/!{/world/{N
    s/\n.*//g}}' my_file

输出

hello world
I DON'T want to delete this line since the first pattern is above
world
my name is John
my name is Joe
world
My name is Jack
this is world
rule

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-07-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-09
    • 2016-11-03
    相关资源
    最近更新 更多