我有一個檔案 foo.properties 的內容如下
foo=bar
# another property
test=true
allNames=alpha:.02,beta:0.25,ph:0.03,delta:1.0,gamma:.5
在我的腳本中,我需要替換任何反對ph的值(bash 腳本不知道當前值)并將其更改為 0.5。所以檔案應該看起來像
foo=bar
# another property
test=true
allNames=alpha:.02,beta:0.25,ph:0.5,delta:1.0,gamma:.5
我知道如果通過使用知道當前值可以輕松完成
sed "s/\,ph\:0.03\,/\,ph\:0.5\,/" foo.properties
但在我的情況下,我必須實際讀取內容allNames并搜索該值,然后在 for 回圈中替換。其余的都處理好了,但我無法弄清楚sed/perl命令。我嘗試使用sed "s/\,ph\:.*\,/\,ph\:0.5\,/" foo.properties和一些變體,但沒有奏效。
uj5u.com熱心網友回復:
一個更簡單的 sed 解決方案:
sed -E 's/([=,]ph:)[0-9.] /\10.5/g' file
foo=bar
# another property
test=true
allNames=alpha:.02,beta:0.25,ph:0.5,delta:1.0,gamma:.5
在這里,我們匹配([=,]ph:)(即,或=后跟ph:)并在組 #1 中捕獲。這后面應該跟 1 個[0-9.]字符以獲取任何數字。作為替代,我們\1放回了0.5
uj5u.com熱心網友回復:
使用您顯示的示例,請嘗試以下awk代碼。
awk -v new_val="0.5" '
match($0,/,ph:[0-9] (\.[0-9] )?/){
val=substr($0,RSTART 1,RLENGTH-1)
sub(/:.*/,":",val)
print substr($0,1,RSTART) val new_val substr($0,RSTART RLENGTH)
next
}
1
' Input_file
詳細說明:創建awk的變數namednew_val包含需要放入的新值。在awk使用match函式awk匹配,ph:[0-9] (\.[0-9] )?每一行正則運算式的主程式中,如果找到匹配的正則運算式,則將該匹配值存盤到變數中val。然后:用:此處替換val 變數中從到到值結束的所有內容。然后列印值作為 OP 的先決條件(匹配 regex 值之前的值與 val(regex 中編輯的匹配值)與新值和其余行),使用 next 將避免走得更遠,并通過提及1列印其余沒有的行其中匹配的值。
第二個解決方案:使用sub的功能awk。
awk -v newVal="0.5" '/^allNames=/{sub(/,ph:[^,]*/,",ph:"newVal)} 1' Input_file
uj5u.com熱心網友回復:
請您嘗試一個perl解決方案:
perl -pe '
s/(?<=\bph:)[\d.] (?=,|$)/0.5/;
' foo.properties
- 該
-pe選項可以perl逐行讀取輸入,執行操作,然后按原樣列印sed。 - 正則運算式
(?<=\bph:)是一個零長度的lookbehind,它匹配ph:前面有一個單詞邊界的字串。 - 正則運算式
[\d.]將匹配一個十進制數。 - 正則運算式
(?=,|$)是一個零長度的前瞻,它匹配逗號或字串的結尾。 - 由于lookbehind 和lookahead 的長度為零,因此它們不會被
s/../../運算子替換。
[編輯]
正如 Dave Cross 評論的(?=,|$)那樣,只要輸入檔案的格式正確,就不需要前瞻。
uj5u.com熱心網友回復:
在行中的任何位置使用小數位與否,或沒有值。
sed -E 's/(^|[^-_[:alnum:]])ph:[0-9]*(.[0-9] )?/ph:0.5/g'
或者可能:
sed -E 's/(^|[=,[:space:]])ph:[0-9] (.[0-9] )?/ph:0.5/g'
頂部的使用“非其他命名字符”來描述緊鄰名稱之前的字符,底部的使用分隔符(您可以添加更多字符)。目的是避免與other_ph或發生沖突autograph。
uj5u.com熱心網友回復:
干得好
#!/usr/bin/perl
use strict;
use warnings;
print "\nPerl Starting ... \n\n";
while (my $recordLine =<DATA>)
{
chomp($recordLine);
if (index($recordLine, "ph:") != -1)
{
$recordLine =~ s/ph:.*?,/ph:0.5,/g;
print "recordLine: $recordLine ...\n";
}
}
print "\nPerl End ... \n\n";
__DATA__
foo=bar
# another property
test=true
allNames=alpha:.02,beta:0.25,ph:0.03,delta:1.0,gamma:.5
輸出:
Perl Starting ...
recordLine: allNames=alpha:.02,beta:0.25,ph:0.5,delta:1.0,gamma:.5 ...
Perl End ...
uj5u.com熱心網友回復:
在每個 Unix 機器上的任何 shell 中使用任何 sed(發布的其他使用sed -E需要 GNU 或 BSD sed 的 sed 解決方案):
a) ifph:永遠不是allNames串列中的第一個標簽(如您的示例輸入所示):
$ sed 's/\(,ph:\)[^,]*/\10.5/' foo.properties
foo=bar
# another property
test=true
allNames=alpha:.02,beta:0.25,ph:0.5,delta:1.0,gamma:.5
b) 或者如果它可以是第一個:
$ sed 's/\([,=]ph:\)[^,]*/\10.5/' foo.properties
foo=bar
# another property
test=true
allNames=alpha:.02,beta:0.25,ph:0.5,delta:1.0,gamma:.5
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/362217.html
