我有一個命令以以下格式輸出文本:
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 之外解決這個問題的方式。
感謝任何指導。我確定我錯過了一些相對簡單的東西。
uj5u.com熱心網友回復:
單程
my @values = map { /\bvar(?:1|2|3)\s*=\s*(.*)/ ? $1 : () } qx(command);
qx運算子( “反引號”)在串列context中使用時回傳所有輸出行的串列,此處由map強加。(在標量背景關系中,它回傳字串中的所有輸出,可能是多行。)然后map提取所需的值:其中的三元運算子回傳捕獲,或者當沒有匹配時回傳一個空串列(因此過濾掉這些行)。請根據需要調整正則運算式。
或者可以將其分解,獲取所有輸出,然后過濾所需的行,然后決議它們。這允許進行更細微的分階段處理。然后還有一些用于管理外部命令的庫,這些庫使更多的參與作業變得更好。
對問題中顯示的 Perl 嘗試的評論
由于反引號被分配給標量,因此它在標量背景關系中,因此回傳字串中的所有輸出,這里是多行。然后下面的正則運算式替換var1=(.*)為$1,留下接下來的兩行,因為.不匹配換行符,所以.*在第一個換行符處停止。
因此,您需要修改該正則運算式以匹配所有其余部分,以便將其全部替換為 capture $1。但是對于其他變數,模式必須有所不同。或者,可以用所有三個值替換輸入字串var,但是你會有一個包含這三個值的字串。
所以總的來說:在這里使用替換 ( s///) 是不合適的——只需使用匹配m//。
由于在串列背景關系中,匹配運算子還回傳所有匹配項,另一種方式是
my @values = qx(command) =~ /\bvar(?:1|2|3)\s*=\s*(.*)/g;
現在被系結到正則運算式,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;
現在mapfor 的每一行輸出都command回傳一對 var-name value,并且可以將這些對的串列分配給哈希。在第二種情況下,后續匹配(下/g)也是如此。
uj5u.com熱心網友回復:
在標量背景關系中,s///回傳s///g 是否找到匹配項。所以你可以使用
print $s if $s =~ s///;
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/475692.html
