我的輸入文件是GAWK - 有條件的(即依賴於正則表達式匹配)查找/一些轉換器功能替代
input.txt中:
News A 1 B 2h 0m 1s C text1
100 A 2 B 120m 1s C text2
Show A 3 B 450s C text3
Tom A 4 B 0:30 C text4
Laura A 5 B 20 C text5
Something A 6 B 1h 100m 70s C text6
50 A 7 B 10s C text7
(你看怪異的時間格式在第6行,但這是故意的,只是爲了演示,以簡化邏輯,而不需要額外的0-59
)。
我想下面的正則表達式適用於每一行:
^(.*?)\sA\s(.*?)\sB\s(.*?)\sC\s(.*?)$
注意語法\3
。有效的變體:
\d{1,}h \d{1,}m \d{1,}s
\d{1,}m \d{1,}s
\d{1,}s
\d{1,}
等於\d{1,}s
我需要將其轉換成秒,但如果這部分無法通過此驗證,保持原樣。無論如何,讓我們將結果命名爲$sec
。
我需要定義以下的正則表達式的變量:
$price == '\d{1,} ', $names == 'Bob|Tom|Laura|Sandra', $tags == 'News|Show'
(或(?:regex)
語法,我不知道哪個是更好地在這裏)
然後,替換爲以下行:
如果
\1 ~ $price
:"ID: \1; time: $sec seconds; description: \1 – buy for $\1!
如果
\1 ~ $names
:description: \4 from @\1; time: $sec seconds
如果
\1 ~ $tags
:ID: \2; #\1; time: $sec seconds; description: \4
否則(如果
\1
不匹配任何預定義的正則表達式的變量,或多於一個的可變匹配) :ID: \2; time: $sec seconds; \1; description: \4
所以輸出文件應
輸出。TXT:
ID: 1; #News; time: 7201 seconds; description: text1
ID: 2; time: 7201 seconds; description: text2 – buy for $100!
ID: 3; #Show; time: 450 seconds; description: text3
description: text4 from @Tom; time: 0:30
description: text5 from @Laura; time: 20 seconds
ID: 6; time: 9670 seconds; Something; description: text6
ID: 7; time: 10 seconds; description: text7 – buy for $50!
我用這個代碼:
gawk -F '\\|' 'function _time(str) {
if (str ~ /([[:digit:]]+)h\s([[:digit:]]+)m\s([[:digit:]]+)s/) {
match(str, /([[:digit:]]+)h\s([[:digit:]]+)m\s([[:digit:]]+)s/, arr)
return arr[1]*3600+arr[2]*60+arr[3] }
else if (str ~ /([[:digit:]]+)m\s([[:digit:]]+)s/) {
match(str, /([[:digit:]]+)m\s([[:digit:]]+)s/, arr)
return arr[1]*60+arr[2] }
else if (str ~ /([[:digit:]]+)s/ || str ~ /([[:digit:]]+)/) {
match(str, /([[:digit:]]+).*?/, arr)
return arr[1] }
else
return str }
match($0, /^(.*?)\sA\s(.*?)\sB\s(.*?)\sC\s(.*?)$/, _f)
{ if (_f[1] ~ /[[:digit:]]+/) {
printf "ID: %s; time: %s seconds; description: %s – buy for $%s\n", _f[2], _time(_f[3]), _f[4], _f[1] }
else if (_f[1] ~ /Bob|Tom|Laura|Sandra/) {
printf "description: %s from %s; time: %s seconds\n", _f[4], _f[1], _time(_f[3]) }
else if (_f[1] ~ /News|Show/) {
printf "ID: %s; #%s; time: %s seconds; description: %s\n", _f[2], _f[1], _time(_f[3]), _f[4] }
else {
printf "ID: %s; time: %s seconds; %s; description: %s\n", _f[2], _time(_f[3]), _f[1], _f[4] } }' input.txt > output.txt.
,得到了四個方面的問題。
- 爲什麼我在輸出行之前看到輸入行?我希望輸入行是替換爲與結果行!
- 爲什麼我在第8條輸出線看到
0 seconds
?我預計會看到0:30 seconds
。爲什麼0:30
匹配/([[:digit:]]+)s/ || /([[:digit:]]+)/)
?我預計else return str
在這裏行動(保持0:30
原樣)。 - 我使用
if (_f[1] ~ /regex/)
語法,但我不知道如何將/regex/
放入變量。當我把它變成變量時,它不起作用。 - 我不知道AWK如何工作的內部。是否每條件測試?如果是,
_f[1]
匹配多個條件時應該怎麼做(if (_f[1] ~ /X|A/) { ... } else if (_f[1] ~ /A|B/) { ... }
)?我想把這個案例放入else {}
。如果不是,我會選擇立即打印第一場比賽的結果,以提高表現。
附加說明:我使用Cygwin 命令行,而無需使用單獨的.awk
文件的代碼。
這GAWK的版本?對於0:30,它與你最後一個正則表達式'/([[:digit:]] +)/)'相匹配,因爲0是一個數字,你用一個或多個數字進行測試。你可以通過指定正則表達式的開始和結束來得到更好的結果,例如:'/^[[:digit:]] + $ /'創建捕獲組的括號在比較中是無用的。其餘的我會做測試,起初它不適用於我的gawk版本3.1.7 – Tensibai 2014-11-22 10:53:07
我看不到樹林。我想你的主要問題是如何將人類可讀的時間戳轉換爲秒,不是嗎? – Jdamian 2014-11-22 11:04:49
而不是'/ regex /',你可以'match($ 0,regex)' – 2014-11-22 15:39:02