Perl 正则表达式 - 仅打印修改后的行(如 sed -n 's///p')
Perl regex - print only modified line (like sed -n 's///p')
我有一个命令可以输出以下格式的文本:
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=\(.*\)$//p')
VAR2=$(echo "${OUTPUT}" | sed -ne 's/^var2=\(.*\)$//p')
VAR3=$(echo "${OUTPUT}" | sed -ne 's/^var3=\(.*\)$//p')
用我想要的基本内容填充 OUTPUT(因此我不必多次 运行 原始命令),然后我可以使用 sed VAR1 = [=33 提取每个值=],等等
我过去使用过 perl,但我很生疏。这是我能想到的最好的:
my $output = `command | grep '^var'`;
(my $var1 = $output) =~ s/\bvar1=(.*)\b//m;
print $var1
这正确匹配并引用了 var1 的值,但它也 returns 不匹配的行,因此 $var1 等于:
qwerty
var2=asdfgh
var3=zxcvbn
使用 sed 我可以告诉它只打印修改过的行。有没有办法在 perl 中做类似的事情?我在 perl 中找不到与 sed 的 p 修饰符等价的东西。
相反,有没有更好的方法从每一行中提取那些子字符串?我确定我可以匹配匹配每一行并拆分内容或类似的东西,但我试图坚持使用正则表达式,因为这是我通常在 perl 之外解决这个问题的方式。
感谢任何指导。我确定我遗漏了一些相对简单的东西。
一种方式
my @values = map { /\bvar(?:1|2|3)\s*=\s*(.*)/ ? : () } qx(command);
qx
operator ("backticks") returns a list of all lines of output when used in list context, here imposed by map。 (在标量上下文中,它 returns 所有输出都在一个字符串中,可能是多行。)然后 map
提取想要的值:其中的三元运算符 returns 捕获,或者一个空列表不匹配(因此过滤掉这些行)。请适当调整正则表达式。
或者可以将其分解,获取所有输出,然后过滤需要的行,然后解析它们。这允许进行更细微的分阶段处理。然后还有用于管理外部命令的库,这些库使更多的工作变得更好。
对问题中显示的 Perl 尝试的评论
由于反引号被分配给标量,因此它处于标量上下文中,因此 returns 所有输出都在一个字符串中,这里是多行。然后下面的正则表达式将 var1=(.*)
替换为 </code>,留下接下来的两行,因为 <code>.
不匹配换行符,所以 .*
在第一个换行符处停止。
因此您需要修改该正则表达式以匹配所有其余部分,以便将其全部替换为捕获 </code>。但是对于其他变量,模式必须不同。或者,可以用所有三个 <code>var
值替换输入字符串,但是这样你就会得到一个包含这三个值的字符串。
总而言之:在这里使用替换 (s///
) 是不合适的——只需使用匹配,m//.
因为在列表上下文中匹配运算符也returns所有匹配另一种方式是
my @values = qx(command) =~ /\bvar(?:1|2|3)\s*=\s*(.*)/g;
现在是正则表达式的 bound,qx
在标量上下文中,因此它 returns 是一个(此处为多行)字符串,然后由正则表达式匹配。使用 /g
修饰符,模式通过该字符串保持匹配,捕获所有想要的值(而不是其他)。 .
不匹配换行符所以 .*
在第一个换行符处停止的事实现在很有用。
再次提醒,请根据实际问题调整正则表达式。
另一个需求出现了,即捕获变量的实际名称及其值。然后在名称周围添加捕获括号,并分配给哈希
my %val = map { /\b(var(?:1|2|3))\s*=\s*(.*)/ ? (, ) : () } qx(command);
或
my %val = qx(command) =~ /\b(var(?:1|2|3))\s*=\s*(.*)/g;
现在map
从command
returns的每一行输出一对var-name+值,而这样的对列表可以赋值给一个哈希。在第二种情况下,后续匹配(在 /g
下)也是如此..
在标量上下文中,s///
和 s///g
return 是否找到匹配项。所以你可以使用
print $s if $s =~ s///;
我有一个命令可以输出以下格式的文本:
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=\(.*\)$//p')
VAR2=$(echo "${OUTPUT}" | sed -ne 's/^var2=\(.*\)$//p')
VAR3=$(echo "${OUTPUT}" | sed -ne 's/^var3=\(.*\)$//p')
用我想要的基本内容填充 OUTPUT(因此我不必多次 运行 原始命令),然后我可以使用 sed VAR1 = [=33 提取每个值=],等等
我过去使用过 perl,但我很生疏。这是我能想到的最好的:
my $output = `command | grep '^var'`;
(my $var1 = $output) =~ s/\bvar1=(.*)\b//m;
print $var1
这正确匹配并引用了 var1 的值,但它也 returns 不匹配的行,因此 $var1 等于:
qwerty
var2=asdfgh
var3=zxcvbn
使用 sed 我可以告诉它只打印修改过的行。有没有办法在 perl 中做类似的事情?我在 perl 中找不到与 sed 的 p 修饰符等价的东西。
相反,有没有更好的方法从每一行中提取那些子字符串?我确定我可以匹配匹配每一行并拆分内容或类似的东西,但我试图坚持使用正则表达式,因为这是我通常在 perl 之外解决这个问题的方式。
感谢任何指导。我确定我遗漏了一些相对简单的东西。
一种方式
my @values = map { /\bvar(?:1|2|3)\s*=\s*(.*)/ ? : () } qx(command);
qx
operator ("backticks") returns a list of all lines of output when used in list context, here imposed by map。 (在标量上下文中,它 returns 所有输出都在一个字符串中,可能是多行。)然后 map
提取想要的值:其中的三元运算符 returns 捕获,或者一个空列表不匹配(因此过滤掉这些行)。请适当调整正则表达式。
或者可以将其分解,获取所有输出,然后过滤需要的行,然后解析它们。这允许进行更细微的分阶段处理。然后还有用于管理外部命令的库,这些库使更多的工作变得更好。
对问题中显示的 Perl 尝试的评论
由于反引号被分配给标量,因此它处于标量上下文中,因此 returns 所有输出都在一个字符串中,这里是多行。然后下面的正则表达式将 var1=(.*)
替换为 </code>,留下接下来的两行,因为 <code>.
不匹配换行符,所以 .*
在第一个换行符处停止。
因此您需要修改该正则表达式以匹配所有其余部分,以便将其全部替换为捕获 </code>。但是对于其他变量,模式必须不同。或者,可以用所有三个 <code>var
值替换输入字符串,但是这样你就会得到一个包含这三个值的字符串。
总而言之:在这里使用替换 (s///
) 是不合适的——只需使用匹配,m//.
因为在列表上下文中匹配运算符也returns所有匹配另一种方式是
my @values = qx(command) =~ /\bvar(?:1|2|3)\s*=\s*(.*)/g;
现在是正则表达式的 bound,qx
在标量上下文中,因此它 returns 是一个(此处为多行)字符串,然后由正则表达式匹配。使用 /g
修饰符,模式通过该字符串保持匹配,捕获所有想要的值(而不是其他)。 .
不匹配换行符所以 .*
在第一个换行符处停止的事实现在很有用。
再次提醒,请根据实际问题调整正则表达式。
另一个需求出现了,即捕获变量的实际名称及其值。然后在名称周围添加捕获括号,并分配给哈希
my %val = map { /\b(var(?:1|2|3))\s*=\s*(.*)/ ? (, ) : () } qx(command);
或
my %val = qx(command) =~ /\b(var(?:1|2|3))\s*=\s*(.*)/g;
现在map
从command
returns的每一行输出一对var-name+值,而这样的对列表可以赋值给一个哈希。在第二种情况下,后续匹配(在 /g
下)也是如此..
在标量上下文中,s///
和 s///g
return 是否找到匹配项。所以你可以使用
print $s if $s =~ s///;