我正在试图找出是否有一种方法可以检测并且是否填充了匹配变量(在正则表达式中),以便可以在一个内衬中使用它。如果变量被填充,我想要前置或后置我不会的文本:
在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正则表达式可以做的吗?
我正在寻找一个衬垫,所以我可以将其重命名。但我也很好奇。
答案 0 :(得分:3)
rename 's/document\.(\d\d)\.?(\w+)?(.txt)/"docs $1".($2 && " - $2").$3/e' document.*.txt
答案 1 :(得分:1)
sed
未实现非贪婪重复。 .*?
表示"任意数量的字符后跟文字?" (除非你指定了扩展的正则表达式格式,在这种情况下它只是意味着"任意数量的字符",完全像.*
9
在sed
替换中,"替换捕获N"的语法是\N
(仅限一位数,因此最多允许9次捕获)。 $1
和${2}
都被视为文字替换。
除非您指定-r
(对于Gnu sed;它在BSD seds上的-E
),否则您需要使用基本正则表达式,其中捕获被{{包围1}}和\(
代替\)
和(
。 (还有)
运算符和显式重复;例如,+
。)
[0-9]\{2\}
始终意味着"任何角色"。如果您想匹配。,请使用.
现在,如果您只想匹配非空序列,则可以使用\.
(或.\+
只使用.+
),这样您就可以使用-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