如何删除当前行中的最后一个单词,但前提是下一行出现模式?
How can I delete the last word in the current line, but only if a pattern occurs on the next line?
文件内容为
some line DELETE_ME
some line this_is_the_pattern
如果 this_is_the_pattern
出现在 下一个 行,则删除当前行的最后一个单词(在本例中为 DELETE_ME
)。
如何使用 sed 或 awk 执行此操作?我的理解是 sed 比 awk 更适合这个任务,因为 awk 适合对以表格格式存储的数据进行操作。如果我的理解不正确,请告诉我。
$ awk '/this_is_the_pattern/{sub(/[^[:space:]]+$/, "", last)} NR>1{print last} {last=[=10=]} END{print last}' file
some line
some line this_is_the_pattern
工作原理
此脚本使用一个名为 last
的变量,其中包含文件中的前一行。总之,如果当前行包含该模式,则从 last
中删除最后一个单词。否则,last
将按原样打印。
详细来说,依次执行每条命令:
/this_is_the_pattern/{sub(/[^[:space:]]+$/, "", last)}
如果此行有模式,请删除最后一行的最后一个词。
NR>1{print last}
对于第一行之后的每一行,打印最后一行。
last=[=16=]
将当前行保存在变量 last
.
END{print last}
打印文件的最后一行。
awk 'NR>1 && /this_is_the_pattern/ {print t;}
NR>1 && !/this_is_the_pattern/ {print f;}
{f=[=10=];$NF="";t=[=10=]}
END{print f}' input-file
请注意,这将在删除最后一个字段的任何行中修改 whitespace,将 whitespace 的运行压缩为单个 space.
您可以将其简化为:
awk 'NR>1 { print( /this_is_the_pattern/? t:f)}
{f=[=11=];$NF="";t=[=11=]}
END{print f}' input-file
您可以通过以下方式解决挤压白色space问题:
awk 'NR>1 { print( /this_is_the_pattern/? t:f)}
{f=[=12=];sub(" [^ ]*$","");t=[=12=]}
END{print f}' input-file
您可以使用 tac
向后搜索文件,以便您首先看到模式。然后设置一个标志并删除您看到的下一行的最后一个单词。然后在最后,通过tac
将文件反转回原来的顺序。
tac file | awk '/this_is_the_pattern/{f=1;print;next} f==1{sub(/ [^ ]+$/, "");print;f=0}' | tac
使用缓冲区在内存中保留上一行
sed -n 'H;1h;1!{x;/\nPAGE/ s/[^ ]*\(\n\)//;P;s/.*\n//;h;$p;}' YourFile
使用循环但概念相同
sed -n ':cycle
N;/\nPAGE/ s/[^ ]*\(\n\)//;P;s/.*\n//;$p;b cycle' YourFile
在这两种情况下,它都会删除上一行的最后一个单词,而且搜索模式是在连续的 2 行上
使用最后读取的 2 行,测试模式是否在最后,如果存在则删除单词,然后打印第一行,将其删除并循环
惯用的 awk 解决方案只是保留前一行(或一般情况下的 N 行)的缓冲区,这样您就可以测试当前行,然后相应地修改 and/or 打印缓冲区:
$ awk '
NR>1 {
if (/this_is_the_pattern/) {
sub(/[^[:space:]]+$/,"",prev)
}
print prev
}
{ prev = [=10=] }
END { print prev }
' file
some line
some line this_is_the_pattern
文件内容为
some line DELETE_ME
some line this_is_the_pattern
如果 this_is_the_pattern
出现在 下一个 行,则删除当前行的最后一个单词(在本例中为 DELETE_ME
)。
如何使用 sed 或 awk 执行此操作?我的理解是 sed 比 awk 更适合这个任务,因为 awk 适合对以表格格式存储的数据进行操作。如果我的理解不正确,请告诉我。
$ awk '/this_is_the_pattern/{sub(/[^[:space:]]+$/, "", last)} NR>1{print last} {last=[=10=]} END{print last}' file
some line
some line this_is_the_pattern
工作原理
此脚本使用一个名为 last
的变量,其中包含文件中的前一行。总之,如果当前行包含该模式,则从 last
中删除最后一个单词。否则,last
将按原样打印。
详细来说,依次执行每条命令:
/this_is_the_pattern/{sub(/[^[:space:]]+$/, "", last)}
如果此行有模式,请删除最后一行的最后一个词。
NR>1{print last}
对于第一行之后的每一行,打印最后一行。
last=[=16=]
将当前行保存在变量
last
.END{print last}
打印文件的最后一行。
awk 'NR>1 && /this_is_the_pattern/ {print t;}
NR>1 && !/this_is_the_pattern/ {print f;}
{f=[=10=];$NF="";t=[=10=]}
END{print f}' input-file
请注意,这将在删除最后一个字段的任何行中修改 whitespace,将 whitespace 的运行压缩为单个 space.
您可以将其简化为:
awk 'NR>1 { print( /this_is_the_pattern/? t:f)}
{f=[=11=];$NF="";t=[=11=]}
END{print f}' input-file
您可以通过以下方式解决挤压白色space问题:
awk 'NR>1 { print( /this_is_the_pattern/? t:f)}
{f=[=12=];sub(" [^ ]*$","");t=[=12=]}
END{print f}' input-file
您可以使用 tac
向后搜索文件,以便您首先看到模式。然后设置一个标志并删除您看到的下一行的最后一个单词。然后在最后,通过tac
将文件反转回原来的顺序。
tac file | awk '/this_is_the_pattern/{f=1;print;next} f==1{sub(/ [^ ]+$/, "");print;f=0}' | tac
使用缓冲区在内存中保留上一行
sed -n 'H;1h;1!{x;/\nPAGE/ s/[^ ]*\(\n\)//;P;s/.*\n//;h;$p;}' YourFile
使用循环但概念相同
sed -n ':cycle
N;/\nPAGE/ s/[^ ]*\(\n\)//;P;s/.*\n//;$p;b cycle' YourFile
在这两种情况下,它都会删除上一行的最后一个单词,而且搜索模式是在连续的 2 行上
使用最后读取的 2 行,测试模式是否在最后,如果存在则删除单词,然后打印第一行,将其删除并循环
惯用的 awk 解决方案只是保留前一行(或一般情况下的 N 行)的缓冲区,这样您就可以测试当前行,然后相应地修改 and/or 打印缓冲区:
$ awk '
NR>1 {
if (/this_is_the_pattern/) {
sub(/[^[:space:]]+$/,"",prev)
}
print prev
}
{ prev = [=10=] }
END { print prev }
' file
some line
some line this_is_the_pattern