在perl中是否有一种方法可以使用正则表达式替换输入行中的所有文本(单引号内的文本除外(可能不止一个)),我已经使用下面的代码实现了这一点,但想看看是否可以完成使用正则表达式和地图。
while (<>) {
my $m=0;
for (split(//)) {
if (/'/ and ! $m) {
$m=1;
print;
}
elsif (/'/ and $m) {
$m=0;
print;
}
elsif ($m) {
print;
}
else {
print lc;
}
}
}
**Sample input:**
and (t.TARGET_TYPE='RAC_DATABASE' or (t.TARGET_TYPE='ORACLE_DATABASE' and t.TYPE_QUALIFIER3 != 'racinst'))
**Sample output:**
and (t.target_type='RAC_DATABASE' or (t.target_type='ORACLE_DATABASE' and t.type_qualifier3 != 'racinst'))
答案 0 :(得分:2)
您可以试一下。所有一个正则表达式。
$str =~ s/(?:^|'[^']*')\K[^']*/lc($&)/ge;
或者,更清洁,更有据可查(这在语义上等同于上述内容)
$str =~ s/
(?:
^ | # Match either the start of the string, or
'[^']*' # some text in quotes.
)\K # Then ignore that part,
# because we want to leave it be.
[^']* # Take the text after it, and
# lowercase it.
/lc($&)/gex;
g
标志告诉regexp运行所需的次数。 e
告诉我们替换部分(在我们的例子中为lc($&)
)是Perl代码,而不仅仅是文本。 x
让我们在其中放置这些注释,以免regexp完全乱码。
答案 1 :(得分:1)
对于这样简单的工作,您不是对regexp玩得太辛苦了吗?
为什么今天不让孩子“分裂”呢?
#!/usr/bin/perl
while (<>)
{
@F = split "'";
@F = map { $_ % 2 ? $F[$_] : lc $F[$_] } (0..@F);
print join "'", @F;
}
以上内容仅供参考。我们经常将后两行合理地合并为:
print join "'", map { $_ % 2 ? $F[$_] : lc $F[$_] } (0..@F);
还是享受更多,使其成为一线? (在bash shell中)在概念上看起来像:
perl -pF/'/ -e 'join "'", map { $_ % 2 ? $F[$_] : lc $F[$_] } (0..@F);' YOUR_FILE
但是,实际上,我们需要尊重shell并做一些逃避(艰苦的)工作:
perl -pF/\'/ -e 'join "'"'"'", map { $_ % 2 ? $F[$_] : lc $F[$_] } (0..@F);' YOUR_FILE
(单引号的单引号必须变为5个字母:'"'"'
)
如果它对您的工作没有帮助,则可以帮助睡眠。
答案 2 :(得分:0)
Perl单线又一个变种。我使用十六进制\ x27作为单引号
$ cat sql_str.txt
and (t.TARGET_TYPE='RAC_DATABASE' or (t.TARGET_TYPE='ORACLE_DATABASE' and t.TYPE_QUALIFIER3 != 'racinst'))
$ perl -ne ' { @F=split(/\x27/); for my $val (0..$#F) { $F[$val]=lc($F[$val]) if $val%2==0 } ; print join("\x27",@F) } ' sql_str.txt
and (t.target_type='RAC_DATABASE' or (t.target_type='ORACLE_DATABASE' and t.type_qualifier3 != 'racinst'))
$