Regex sed:用匹配的模式替换第n个单词?

Regex sed:用匹配的模式替换第n个单词?,regex,perl,bash,sed,awk,Regex,Perl,Bash,Sed,Awk,我有一个具有以下特征的文本文件: 每行至少有三个单词用空格隔开 单词可以是任何字符或字符串 我已经在一些行中添加了一些注释,其中包含对原始单词进行更改的初步建议,现在我想使用sed来为我进行这些更改。因此,为了更清楚地了解情况,我的文件如下所示: NO NO O SIGNS NN O #NNS GIVEN VBD B-VP #VBN AT IN O THIS NN O TIME NN O ## B-NP . PER O ... 带1的注释替换一行

我有一个具有以下特征的文本文件:

每行至少有三个单词用空格隔开 单词可以是任何字符或字符串 我已经在一些行中添加了一些注释,其中包含对原始单词进行更改的初步建议,现在我想使用sed来为我进行这些更改。因此,为了更清楚地了解情况,我的文件如下所示:

NO NO O
SIGNS NN O      #NNS
GIVEN VBD B-VP  #VBN
AT IN O
THIS NN O       
TIME NN O            ## B-NP
. PER O
...
带1的注释替换一行中的第二个单词,带2的注释替换一行中的第三个单词。有没有人能建议一种方法来使用sed或awk,或者其他什么?希望再次澄清,我的目标是得到or后面的模式,并用匹配的模式替换行的第n个单词


谢谢。

这将对您有用:

awk '/#/{sub(/# +/,"#");n=gsub(/#/,"",$NF);$(n+1)=$NF;$NF="\t\t#"}1' file
sed 's/\S*\(\s*\S*\s*#\s*\)\([^#]*\)$/\2\1/;s/ *##*.*/\t\t#/' file
NO NO O
SIGNS NNS O             #
GIVEN VBN B-VP          #
AT IN O
THIS NN O       
TIME NN B-NP            #
. PER O
...
解释 //{…}:搜索包含并执行以下步骤的行。。。 sub/+/,:如有必要,删除注释和注释之间的所有空格 n=gsub/,$NF:从最后一个字段$NF中删除所有,并将删除的数量设置为变量n $n+1=$NF:将n+1字段$n+1设置为新的最后一个字段$NF,该字段已剥离所有 $NF=\t\t:将最后一个字段$NF设置为两个选项卡,后跟一个 1:告诉awk打印更改行的快捷方式 文件:您的输入文件 实例
注意:如果你的笔记总是跟在后面,中间没有空格,你可以删除整个子/+/,;命令的一部分,使其更短

这可能适用于您:

awk '/#/{sub(/# +/,"#");n=gsub(/#/,"",$NF);$(n+1)=$NF;$NF="\t\t#"}1' file
sed 's/\S*\(\s*\S*\s*#\s*\)\([^#]*\)$/\2\1/;s/ *##*.*/\t\t#/' file
NO NO O
SIGNS NNS O             #
GIVEN VBN B-VP          #
AT IN O
THIS NN O       
TIME NN B-NP            #
. PER O
...

Perl可以处理这个问题。虽然我想我更喜欢把它写成剧本

粘贴版本:

perl -lnwe 's/#\K\s+//; my @a=/\S+/g; if (@a>3) { $c = $a[3] =~ tr/#//d; $a[$c] = $a[3]; } print join " ", @a[0..2]' file
此版本将打印到标准输出,而不会更改文件。添加-i.bak,例如perl-i.bak-lnwe'..'进行就地编辑,并在file.bak中进行备份

可读版本:

$ perl -lnwe '       # -l: handle newlines, -n read file/stdin
    s/#\K\s+//;                    # strip optional spaces
    my @a = /\S+/g;                # extract the data
    if (@a > 3) {                  # when there are replacements..
        my $c = $a[3] =~ tr/#//d;  # count and remove #
        $a[$c] = $a[3];            # set element number $c to element 3
    } print join " ", @a[0..2]     # reassemble and print 3 first elements
' file
输出:


有没有可能规定你的笔记后面有一个预定的空格?现在,您显示的注释后面都有零和一个空格,这使得代码不必要地难以容纳这些空格。如果你的笔记后面有零个空格,那就容易多了。另外,你想让笔记在输出中吗?@SiegeX:是的,我应该可以很容易地删除B-NP中的多余空格,或者根据需要在NNS中添加空格。@SiegeX:否,我不希望在输出中显示注释-我确实希望在输出后保留一个标记,如两个制表符,以指定我更改的行。谢谢。我不熟悉awk,所以我必须做一些研究来了解这里发生了什么。不过,我真的无法将你的笔记转换成其他命令。它会是:awk'/{;t=$NF;n=gsub//,t;$n+1=t}1'注释吗??这看起来有点奇怪…它应该是/{n=gsub/,$NF;$n+1=$NF;$NF=\t\t}1'文件我刚刚在我的文件上运行了你的命令,它似乎工作得很好。我真是太感谢你了。@wayeast没问题,你可以从接受答案开始=是的,这也行。我花了最长的时间在sed中尝试这样做,我想出的命令简直是噩梦。解释器一直告诉我我的/1和/2标识符无效。这里的技巧是将regexp锚定到字符串$的末尾,并使用额外的参数将引用向后拉近一个字段,请参见\\s*\s*\s*\。