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

时间:2012-02-16 01:23:42

标签: regex perl bash sed awk

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

  1. 每行至少有三个“单词”用空格分隔
  2. “word”可以是任何字符或字符串
  3. 我在一些行中添加了一些注释,并提供了对原始单词进行更改的暂时建议,现在我想使用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#的注释是替换行中的SECOND字,2#的注释是替换行中的THIRD字。有人能用sed(或awk,或其他任何东西)建议一种方法吗?再次澄清(希望),我的目标是在#或##之后获得模式,并用匹配的模式替换该行的第n个单词。

    感谢。

3 个答案:

答案 0 :(得分:4)

这对你有用:

awk '/#/{sub(/# +/,"#");n=gsub(/#/,"",$NF);$(n+1)=$NF;$NF="\t\t#"}1' file

解释

  1. /#/{ ... }:搜索包含#的行并执行以下步骤...
  2. sub(/# +/,"#"):删除备注与#之间的所有空格
  3. n=gsub(/#/,"",$NF):从最后一个字段#中删除所有$NF,并将#的数量设置为变量n
  4. $(n+1)=$NF:将n + 1字段$(n+1)设置为新的最后一个字段$NF,其中#已被剥离
  5. $NF="\t\t#":将最后一个字段$NF设置为两个标签,后跟#
  6. 1:告诉awk打印更改后的行
  7. 的快捷方式
  8. file:您的输入文件
  9. 实施例

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

    注意 :如果您这样做,那么您的笔记始终跟在#之间,其间的空格为零,则可以移除整个sub(/# +/,"#");命令的一部分,使其更短

答案 1 :(得分:1)

这可能对您有用:

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
...

答案 2 :(得分:0)

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

此版本将打印到stdout而不更改文件。添加-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

<强>输出:

NO NO O
SIGNS NNS O
GIVEN VBN B-VP
AT IN O
THIS NN O
TIME NN B-NP
. PER O