regex - Perl 正则表达式 - 仅打印修改后的行(如 sed -n 's///p' )

标签 regex perl

我有一个输出以下格式文本的命令:

misc1=poiuyt
var1=qwerty
var2=asdfgh
var3=zxcvbn
misc2=lkjhgf

等我需要将 var1、var2 和 var3 的值获取到 perl 脚本中的变量中。

如果我正在编写一个 shell 脚本,我会这样做:

OUTPUT=$(command | grep '^var-')
VAR1=$(echo "${OUTPUT}" | sed -ne 's/^var1=\(.*\)$/\1/p')
VAR2=$(echo "${OUTPUT}" | sed -ne 's/^var2=\(.*\)$/\1/p')
VAR3=$(echo "${OUTPUT}" | sed -ne 's/^var3=\(.*\)$/\1/p')

用我想要的基本内容填充 OUTPUT(这样我就不必多次运行原始命令),然后我可以使用 sed VAR1 = 'qwerty' 等提取每个值。

我过去使用过 perl,但我很生疏。这是我能想到的最好的:

my $output = `command | grep '^var'`;
(my $var1 = $output) =~ s/\bvar1=(.*)\b/$1/m;
print $var1

这正确匹配并引用了 var1 的值,但它也返回了不匹配的行,因此 $var1 等于:

qwerty
var2=asdfgh
var3=zxcvbn

使用 sed 我可以告诉它只打印修改过的行。有没有办法在 perl 中做类似的事情?我在 perl 中找不到与 sed 的 p 修饰符等价的东西。

相反,是否有更好的方法从每一行中提取那些子字符串?我确定我可以匹配匹配每一行并拆分内容或类似的东西,但我试图坚持使用正则表达式,因为这是我通常在 perl 之外解决这个问题的方式。

感谢任何指导。我确定我遗漏了一些相对简单的东西。

最佳答案

单向

my @values = map { /\bvar(?:1|2|3)\s*=\s*(.*)/ ? $1 : () } qx(command);

qx operator ("backticks") 在列表 context 中使用时返回所有输出行的列表, 这里由 map 强加. (在标量上下文中,它返回一个字符串中的所有输出,可能是多行。)然后 map 提取想要的值:其中的三元运算符返回捕获,或者在没有匹配时返回一个空列表(所以过滤掉这些行)。请适当调整正则表达式。

或者可以将其分解,获取所有输出,然后过滤需要的行,然后解析它们。这允许进行更细微的分阶段处理。然后还有用于管理外部命令的库,这些库使更多的工作变得更好。


对问题中显示的 Perl 尝试的评论

由于反引号被分配给一个标量,它处于标量上下文中,因此返回字符串中的所有输出,此处为多行。然后下面的正则表达式将 var1=(.*) 替换为 $1,因为 . 不匹配换行符所以留下接下来的两行.* 在第一个换行符处停止。

因此您需要修改该正则表达式以匹配所有其余部分,以便将其全部替换为捕获 $1。但是对于其他变量,模式必须不同。或者,可以用所有三个 var 值替换输入字符串,但这样您就会得到一个包含这三个值的字符串。

总而言之:在这里使用替换 (s///) 是不合适的——只需使用匹配,m// .

因为在列表上下文中,匹配运算符也以另一种方式返回所有匹配

my @values = qx(command) =~ /\bvar(?:1|2|3)\s*=\s*(.*)/g;

现在是bound对于正则表达式,qx 在标量上下文中,因此它返回一个(此处为多行)字符串,然后由正则表达式匹配。使用 /g 修饰符,模式通过该字符串保持匹配,捕获所有想要的值(而不是其他任何值)。 . 不匹配换行符,因此 .* 在第一个换行符处停止这一事实现在很有用。

再次强调,请根据实际问题调整正则表达式。


另一个需求出现了,即捕获变量的实际名称及其值。然后在名称周围添加捕获括号,并分配给哈希

my %val = map { /\b(var(?:1|2|3))\s*=\s*(.*)/ ? ($1, $2) : () } qx(command);

my %val = qx(command) =~ /\b(var(?:1|2|3))\s*=\s*(.*)/g;

现在 command 的每一行输出的 map 返回一对 var-name + value,并且可以将这样的对列表分配给哈希。在第二种情况下,后续匹配(在 /g 下)也是如此。

关于regex - Perl 正则表达式 - 仅打印修改后的行(如 sed -n 's///p' ),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72179071/

相关文章:

perl - Cwd.c : loadable library and perl binaries are mismatched (got handshake key 0xdb00080, 需要 0xde00080)

regex - 使用 perl 表达式批量重命名文件

perl - 与 reftype { } 有什么关系?

perl - 如何使用 perl 脚本将表单数组从 URL 插入到 DBD 数据库?

xml - 在子 libxml perl 之后插入

java - 在java中连接字符串和正则表达式

java - 将java源文件合并为一个

ruby - 如何在 ruby​​ 中用转义单引号替换单引号

regex - Sublime & Regex : How to find all lines that are 3 letters or less, 不包括某些行?

perl - 为什么这里的 STDIN 在列表上下文中工作?