4

我需要将其匹配为替代命令:

whatever__MATCH_THIS__whateverwhatever__AND_THIS__whateverwhatever

我正在尝试:

sed -e 's/__\(.*\)__/\{{\1}}/g' myfile

但这是热切匹配__MATCH_THIS__whateverwhatever__AND_THIS__的,产生:

whatever{{MATCH_THIS__whateverwhatever__AND_THIS}}whateverwhatever

但我想要:

whatever{{MATCH_THIS}}whateverwhatever{{AND_THIS}}whateverwhatever

如何在匹配部分中指定要排除的字符串?我知道如何排除一个字符(例如[^a]),但不知道如何排除一个字符串。

4

6 回答 6

2

您需要的是一个非贪婪的正则表达式,但不幸的是 sed 不允许这样做。但是,它可以在 perl 中完成。

perl -pe 's|__(.*?)__|{{$1}}|g' <myfile

星号后面的问号表示匹配器是非贪婪的,因此不是采用它可以找到的最长匹配字符串,而是采用最短的匹配字符串。

希望有帮助。

如果你想把它放在 perl 脚本中而不是在命令行上运行,那么这样的事情就可以完成:

#! /usr/bin/perl -w
use strict; # Habit of mine
use 5.0100; # So we can use 'say'

# Save the matching expression in a variable. 
# qr// tells us it's a regex-like quote (http://perldoc.perl.org/functions/qr.html)
my $regex = qr/__(.*?)__/;

# Ordinarily, I'd write this in a way I consider to be less perl-y and more readable.
# What it's doing is reading from the filename supplied on STDIN and places the
# contents of the file in $_. Then it runs the substitution on the string, before
# printing out the result.
while (<>) {
  $_ =~ s/$regex/{{$1}}/g;
  say $_;
}

用法很简单:

./regex myfile
whatever{{MATCH_THIS}}whateverwhatever{{AND_THIS}}whateverwhatever

它是 Perl,有一百万零一种方法可以做到!

于 2013-06-01T16:24:17.447 回答
2

GNU sed

sed ':k s/__/{{/;s/__/}}/;tk' file

输入:

whatever__MATCH_THIS__whateverwhatever__AND_THIS__whateverwhatever
blah__XXX_XX__blah_blah_blah__XX_XXX__whateverwhatever

输出:

whatever{{MATCH_THIS}}whateverwhatever{{AND_THIS}}whateverwhatever
blah{{XXX_XX}}blah_blah_blah{{XX_XXX}}whateverwhatever
于 2013-06-02T07:08:23.637 回答
1

sed不支持 PCRE 好东西,例如非贪婪运算符

我能够通过以下变体解决您的情况:

echo 'whatever__MATCH_THIS__whateverwhatever__AND_THIS__whateverwhatever' |
sed -e 's/__\([^_]\+_[^_]\+\)__/\{{\1}}/g'
whatever{{MATCH_THIS}}whateverwhatever{{AND_THIS}}whateverwhatever
于 2013-06-01T16:21:43.273 回答
1

虽然很明显,一种使用方法sed不是完成这项工作的最佳工具。我已经评论了代码以查看会发生什么,因为它似乎有点困惑:

sed -n '
    ## Insert a newline just before each "__". This is the most
    ## important instruction of all the script. The game is that
    ## newline character is the only want that sed cannot find in
    ## a line of data, so use it to know where there will be "__"
    ## to change. For each part changed the script will save it
    ## in hold space, but due to constraints of those (only two
    ## spaces) I will have to play deleting and recovering data
    ## several times between both.
    s/__/\n&/g

    ## Save in hold space all data until first newline.
    ## So it means, just before the first "__" of the line.
    h ; s/\n.*$// ; x

    ## Remove that part just saved in hold space.
    s/^[^\n]*\n//

    ## Set a label to jump it later.
    :a

    ## This is end condition. When not found any newline
    ## in the pattern space means that there are no more "__" to 
    ## process, so get all data saved in hold space, print
    ## it and leave hold space empty ready for next line of 
    ## the input file.
    /^[^\n]\+$/ {
        g
        p
        x
        s/^.*$//
        x
        b
    }

    ## This part of code will process next two input lines.
    ## First one has the first pair of "__" and second one has
    ## the end pair, so substitute to each respective curly
    ## braces.
    s/__/{{/

    ## Once the substitution has been done, save it adding to
    ## hold space.
    ## I add all the line but only want to keep until first newline.
    ## I delete two of them because "H" command adds it one by itself.
    H ; x ; s/\n// ; s/\n.*$// ; x

    ## Delete part just processed and saved in hold space.
    s/^[^\n]*\n//

    ## Repeat same process for end pair of "__"
    s/__/}}/
    H ; x ; s/\n// ; s/\n.*$// ; x
    s/^[^\n]*\n//

    ## Goto label "a"
    ba 
' infile

粘贴并从命令行运行它,只要它产生两行:

whatever{{MATCH_THIS}}whateverwhatever{{AND_THIS}}whateverwhatever
exten => s,n,ExecIf($[${amacode} == 1]?Set(rateparams_view={{INCOMING_RATEPARAMS_VIEW}}):Set(rateparams_view={{OUTGOING_RATEPARAMS_VIEW}}))
于 2013-06-01T17:17:54.343 回答
1

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

sed -r 's/__([^_]+(_[^_]+)*)__/{{\1}}/g' file

或者,也许更容易理解:

sed -r 's/__/\n/g;s/\n([^\n]*)\n/{{\1}}/g;s/\n/__/g' file
于 2013-06-02T14:17:29.313 回答
0

这适用于我的 Windows XP 笔记本电脑

input command
echo whatever__MATCH_THIS__whateverwhatever__AND_THIS__whateverwhatever|sed -f a.sed
output
whatever{{__MATCH_THIS__}}whateverwhatever{{__AND_THIS__}}whateverwhatever
where a.sed is this

    /__MATCH_THIS__/{
    /__AND_THIS__/{
    s/__MATCH_THIS__/\{\{__MATCH_THIS__\}\}/
    s/__AND_THIS__/\{\{__AND_THIS__\}\}/
    }
    }
于 2013-06-01T17:45:39.903 回答