正则表达式一个衬里,它知道是否填充了替代变量

时间:2014-06-30 19:40:27

标签: regex perl bash sed

我正在试图找出是否有一种方法可以检测并且是否填充了匹配变量(在正则表达式中),以便可以在一个内衬中使用它。如果变量被填充,我想要前置或后置我不会的文本:

在Bash中,变量存在的语法是:

$ FOO="asdf"
$ echo ${FOO:+'hello'$FOO}
helloasdf

所以如果我写一个正则表达式搜索并替换:

$ echo "Foo big Bar" | sed -e 's/Foo(.*?)(Bar)/Hello${1}$2/'

$ echo "FooBar" | sed -e 's/Foo(.*?)(Bar)/Hello${1}$2/'

我希望第一个返回类似的内容:“Hello big world”,第二个返回类似“Helloworld”的内容。注意:$ {1}是某种检查......我不知道它是什么样的(因此问题)。如果1美元是空的,我希望它说一件事,如果它不是空的,我希望它说另一个。

让我们尝试一个更好的例子。 名称是:

"document.05.name.txt"
"document.06.txt"

我正在将它们送入相同的正则表达式:

$ echo $name | sed -e 's/document.([0-9]{2}).(.*?).txt/doc $1${2:+ - $2}.txt/s'

再次注意最后的语法是不准确的,因为这就是我想要找到的。 我希望将文档05命名为:“doc 05 - name.txt”和要命名的文档06:“doc 06.txt”注意缺少破折号。

这是perl正则表达式可以做的吗?

我正在寻找一个衬垫,所以我可以将其重命名。但我也很好奇。

4 个答案:

答案 0 :(得分:3)

rename 's/document\.(\d\d)\.?(\w+)?(.txt)/"docs $1".($2 && " - $2").$3/e' document.*.txt

答案 1 :(得分:1)

  1. sed未实现非贪婪重复。 .*?表示"任意数量的字符后跟文字" (除非你指定了扩展的正则表达式格式,在这种情况下它只是意味着"任意数量的字符",完全像.* 9

  2. sed替换中,"替换捕获N"的语法是\N(仅限一位数,因此最多允许9次捕获)。 $1${2}都被视为文字替换。

  3. 除非您指定-r(对于Gnu sed;它在BSD seds上的-E),否则您需要使用基本正则表达式,其中捕获被{{包围1}}和\(代替\)(。 (还有)运算符和显式重复;例如,+。)

  4. [0-9]\{2\}始终意味着"任何角色"。如果您想匹配,请使用.

  5. 现在,如果您只想匹配非空序列,则可以使用\.(或.\+只使用.+),这样您就可以使用-r比赛是非空的。但是aiui,你想做两个不同的比赛,一个是空的,另一个是非空的。因此,您需要提供两个可能的替换命令:

    sed -r -e 's/document\.([0-9]{2})\.(.+)\.txt/document \1 - \2.txt/' \
           -e t \
           -e 's/document\.([0-9]{2})\.txt/document \1.txt/'
    

    如果前面的t命令成功替换了某些内容,s命令将跳到下一个周期。

    注意:我用3个-e选项写出来,因此它不会导致右滚动,但实际上我只使用一个sed命令参数用分号分隔的三个sed命令。

答案 2 :(得分:1)

cat file|perl -pe 's/document\.([0-9]{2})\.((name\.)?txt)/"doc $1". ($3 ? " - $2":".$2")/e'

输出

doc 05 - name.txt
doc 06.txt

答案 3 :(得分:0)

您可以将此perl正则表达式与/e修饰符一起使用:

p='Foo big Bar'    
perl -pe 's/Foo(.*)Bar/my $s=$1; $s =~ s~^\s+|\s+$~~g; $s =~ s~(.+)~ $1 pretty ~; "Hello${s}world"/e' <<< "$p"
Hello big pretty world

p='Foo Bar'    
perl -pe 's/Foo(.*)Bar/my $s=$1; $s =~ s~^\s+|\s+$~~g; $s =~ s~(.+)~ $1 pretty ~; "Hello${s}world"/e' <<< "$p"
Helloworld