我的測驗檔案有如下文本:
> cat test.txt
new dummy("test1", random1).foo("bar1");
new dummy("
test2", random2);
new dummy("test3", random3).foo("bar3");
new dummy = dummy(
"test4", random4).foo("bar4");
我正在嘗試匹配所有以分號 (;) 結尾并具有文本“dummy(”) 的單行。然后我需要提取 dummy 內雙引號中存在的字串。我想出了以下命令,但它只匹配第一個和第三個宣告。
> perl -ne 'print if /dummy/ .. /;/' test.txt | grep -oP 'dummy\((.|\n)*,'
dummy("test1",
dummy("test3",
使用 -o 標志,我希望在虛擬內部的雙引號之間提取字串。但這也行不通。你能給我一個關于如何進行的想法嗎?
預期輸出為:
test1
test2
test3
test4
以下一些答案適用于基本檔案結構。如果行包含超過 1 個換行符,則代碼中斷。例如輸入具有更多換行符的文本檔案:
new dummy("test1", random1).foo("bar1");
new dummy("
test2", random2);
new dummy("test3", random3).foo("bar3");
new dummy = dummy(
"test4", random4).foo("bar4");
new dummy("test5",
random5).foo("bar5");
new dummy("test6", random6).foo(
"bar6");
new dummy("test7", random7).foo("
bar7");
我提到了以下 SO 鏈接:
如何在 grep 中為新行提供模式?
如何grep多行直到; (分號)
uj5u.com熱心網友回復:
這perl應該有效:
perl -0777 -pe 's/(?m)^[^(]* dummy\(\s*"\s*([^"] ).*/$1/g' file
test1
test2
test3
test4
以下gnu-grep tr也應該作業:
grep -zoP '[^(]* dummy\(\s*"\s*\K[^"] "' file | tr '"' '\n'
test1
test2
test3
test4
uj5u.com熱心網友回復:
@TLP 非常接近:
perl -0777 -nE 'say for map {s/^\s |\s $//gr} /\bdummy\(\s*"(. ?)"/gs' test.txt
test1
test2
使用
-0777將檔案作為單個字串插入/\bdummy\(\s*"(. ?)"/gs查找 "dummy(" 之后的所有帶引號的字串內容(在開始引號之前帶有可選的空格)- 該
s標志允許.匹配換行符。 - 任何包含轉義雙引號的字串都會破壞這個正則運算式
- 該
map {s/^\s |\s $//gr}修剪每個字串的前導/尾隨空格。
uj5u.com熱心網友回復:
使用您顯示的示例,請嘗試以下awk代碼,使用 GNU 撰寫和測驗awk。
awk -v RS='(^|\n)new[^;]*;' '
RT{
rt=RT
gsub(/\n |[[:space:]] /,"",rt)
match(rt,/"[^"]*"/)
print substr(rt,RSTART 1,RLENGTH-2)
}
' Input_file
uj5u.com熱心網友回復:
您可以使用Text::ParseWords來提取帶引號的欄位。
use strict;
use warnings;
use Data::Dumper;
use Text::ParseWords;
my $str = do {
local $/;
<DATA>;
}; # slurp the text into a variable
my @lines = quotewords(q("), 1, $str); # extract fields
my @txt;
for (0 .. $#lines) {
if ($lines[$_] =~ /\bdummy\s*\(/) {
push @txt, $lines[$_ 1]; # target text will be in fields following "dummy("
}
}
s/^\s |\s $//g for @txt; # trim leading/trailing whitespace
print Dumper \@txt;
__DATA__
new dummy("test1", random1).foo("bar1");
new dummy("
test2", random2);
new dummy("test3", random3).foo("bar3");
new dummy = dummy(
"test4", random4).foo("bar4");
輸出:
$VAR1 = [
'test1',
'test2',
'test3',
'test4'
];
uj5u.com熱心網友回復:
鑒于:
$ cat file
new dummy("test1", random1).foo("bar1");
new dummy("
test2", random2);
new dummy("test3", random3).foo("bar3");
new dummy = dummy(
"test4", random4).foo("bar4");
你可以這樣使用 GNU grep:
$ grep -ozP '[^;]*\bdummy[^";]*"\s*\K[^";]*[^;]*;' file | tr '\000' '\n' | grep -oP '^[^"]*'
test1
test2
test3
test4
更健壯一些,如果這是一個;分隔文本,您可以:
- 分裂在
;; - 過濾
/\bdummy\b/; - 抓住引號中的第一個欄位;
- 去掉空格。
這是 a 中的所有內容ruby:
ruby -e 'puts $<.read.split(/(?<=;)/).
select{|b| b[/\bdummy\b/]}.
map{|s| s[/(?<=")[^"]*/].strip}' file
# same output
uj5u.com熱心網友回復:
awk基于解決方案通過以下方式處理所有內容FS:
<test1.txt gawk -b -e 'BEGIN { RS="^$"
FS="((^|\\n)?"(___="[^\\n")"] y[(]"(_="[ \\t\\n]*")(__="[\\42]")(_)\
"|"(_="[ \\t]*")(__)(_)"[,]"(___)";] [;][\\n]) "} sub(OFS=ORS,"",$!--NF)'
test1
test2
test3
test4
gawk2 million rows以at為基準 5.15 secs,因此除非您的輸入檔案超出100 MB,否則就足夠了。
*** 警告:避免mawk-1.9.9.6與此解決方案一起使用
uj5u.com熱心網友回復:
建議簡單gawk腳本(標準 linux awk):
awk '/dummy/{print gensub("[[:space:]]*","",1,$2)}' RS=';' FS='"' input.txt
解釋:
RS=';' 將awk記錄分隔符設定為;
FS='"' 將awk欄位分隔符設定為"
/dummy/ 僅過濾匹配dummyRexExp 的記錄
gensub("[[:space:]]*","",1,$2)從第二個欄位的開頭修剪任何空格
print gensub("[[:space:]]*","",1,$2)列印修剪的第二個欄位
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/464647.html
