我有一個包含以下文本的檔案:
<div>
<b>a:</b> <a class='a' href='/a/1'>a1</a><br>
<b>b:</b> <a class='b' href='/b/2'>b2</a><br>
<b>c:</b> <a class='c' href='/c/3/'>c3</a><br>
<b>d:</b> "ef"<br><br><div class='start'>123
<br>ghij.
<br>klmn
<br><br><b>end</b>
</div>
</div>
我想做以下事情:
- 每當一行以 開頭時
<b>a:</b> <a class='a',我想復制>符號之間的文本<a class='a'和</a>- 它必須存盤在a[1]; - 同樣,每當一行以 開頭時
<b>b:</b> <a class='b',我想復制>符號之間的文本<a class='b'和</a>- 它必須存盤在b[1]; - 每當一行包含
<div class='start'>時,我想創建一個變數t,其值以該行和結尾之間出現的文本開頭<div class='start'>,然后設定flag為1; - 如果 的值
flag已經是1并且當前行不以 開頭<br><br><b>end</b>,我想將當前行附加到變數的當前值t(使用空格符號作為分隔符); - 如果 的值
flag已經是1并且當前行以 開頭<br><br><b>end</b>,我想連接三個當前值a[1],b[1]和t(;用作分隔符)并將結果列印到輸出檔案,然后設定flag為0,然后清除變數t。
我使用了以下代碼(用于gawk 4.0.1):
gawk 'BEGIN {flag = 0; t = ""; }
{
if ($0 ~ /^<b>a:<\/b> <a class=\x27a\x27/ ) {
match($0, /^<b>a:<\/b> <a class=\x27a\x27 href=\x27\/a\/[0-9]{1,}\x27>(.*)<\/a>/, a) };
if ($0 ~ /^<b>b:<\/b> <a class=\x27b\x27/ ) {
match($0, /^<b>b:<\/b> <a class=\x27b\x27 href=\x27\/b\/[0-9]{1,}\x27>(.*)<\/a>/, b) };
if ($0 ~ /<div class=\x27start\x27>/ ) {
match($0, /^.*<div class=\x27start\x27>(.*)$/, s);
t = s[1];
flag = 1 };
if (flag == 1) {
if ($0 ~ /^<br><br><b>end<\/b>/) {
str = a[1] ";" b[1] ";" t;
print(str) > "output.txt";
flag = 0; str = ""; t = "" }
else {
t = t " " $0 }
}
}' input.txt
我期待以下輸出:
a1;b2;123 <br>ghij. <br>klmn
但輸出是:
;;123 <b>d:</b> "ef"<br><br><div class='start'>123 <br>ghij. <br>klmn
為什么都是a[1]和b[1]空的?為什么會<b>d:</b> "ef"<br><br><div class='start'>出現在輸出中?如何修復代碼以獲得預期的輸出?
uj5u.com熱心網友回復:
以下是您的具體問題的答案:
Q) 為什么是
a[1]和b[1]空的?A)當我使用 gawk 5.1.1 嘗試您的腳本時,它們不是,所以很可能您的 awk 版本中存在錯誤,或者您輸入中的某些空白不是您的腳本需要的空白(可能是選項卡),或者你有一些控制字符或者你的 awk 版本不喜歡使用
\x27而不是\047for's。Q) 為什么會
<b>d:</b> "ef"<br><br><div class='start'>出現在輸出中?A)因為您忘記了
next匹配的塊中的a ,div所以下一個塊也在執行并$0從該div行保存。問)如何修復代碼以獲得預期的輸出?
A)這是我解決問題的方法,使用 GNU awk 作為第三個引數
match()和\s簡寫[:space:]:
$ cat tst.sh
#!/usr/bin/env bash
gawk '
BEGIN { OFS=";" }
match($0, /^<b>(.):<\/b>\s <a\s class=\047.\047\s href=\047\/.\/[0-9] \/?\047>(.*)<\/a>/, arr) {
vals[arr[1]] = arr[2]
}
match($0, /^.*<div\s class=\047start\047>(.*)/, arr) {
vals["div"] = arr[1]
inDiv = 1
next
}
inDiv {
if ( /^<br><br><b>end<\/b>/ ) {
print vals["a"], vals["b"], vals["div"]
delete vals
inDiv = 0
}
else {
vals["div"] = vals["div"] " " $0
}
}
' 'input.txt' > 'output.txt'
$ ./tst.sh
$ cat output.txt
a1;b2;123 <br>ghij. <br>klmn
所以
- 為了一致性、簡潔性和可維護性,我使用單個
match()來捕獲看起來像 a、b、c 行的所有值。 - 我總是將匹配結果保存在一個名為的陣列中,
arr而不是每次出現的不同陣列中,因此我不必記住不斷洗掉這些陣列,并且使用匹配項的代碼都可以同質化。 - 我使用單個關聯陣列
vals[]來保存由字母索引的所有值,<b>因此我們不需要測驗這些字母并創建單獨的變數,只需洗掉陣列即可輕松清除資料,而不必設定多個變數為空,如果需要,稍后可以輕松地將c或任何其他類似的值添加到輸出中。 - 我
\s對輸入中的每個空格都使用而不是單個空白字符,以不知道實際的空格字符和使用的空格數。 - 我使用
\047而不是\x27匹配's 以獲得可移植性和穩健性,請參閱http://awk.freeshell.org/PrintASingleQuote。 - 我讓 shell 處理所有輸入/輸出,而不是在 awk 腳本中包含輸出重定向,以便在無法打開的檔案等錯誤場景中保持一致性并提高魯棒性。
- 我命名了我的標志變數
inDiv,而不是flag讓它告訴我們它的含義,即我們在div輸入塊中,以提高清晰度并便于將來維護。命名標志變數flag就像命名數字變數number而不是sum,count,ave,或其他可以改進腳本的有意義tot的diff東西。當您看到人們使用f標志變數的名稱時,它f是 的簡寫found,而不是flag。
uj5u.com熱心網友回復:
證明 gawk 的正則運算式與 perl 的不匹配
perl:
$ echo aaaab | perl -nE '/a*(a b)/ && say $1'
ab
$ echo aaaab | perl -nE '/a*?(a b)/ && say $1'
aaaab
a*?匹配零個或多個 a 的最短序列,貪婪者a 消耗其余的。
呆呆
$ echo aaaab | gawk 'match($0, /a*(a b)/, m) {print m[1]}'
ab
$ echo aaaab | gawk 'match($0, /a*?(a b)/, m) {print m[1]}'
ab
不一樣的行為:a*?仍然是貪婪的。
uj5u.com熱心網友回復:
為什么(...)
a[1](...)空?
match0如果發現不匹配,函式會回傳,這樣可以輕松檢查是否是這種情況,我選擇了與填充陣列有關的部分并對其進行了一些更改
{
if ($0 ~ /^<b>a:<\/b> <a class=\x27a\x27/ )
{
print NR, match($0, /^<b>a:<\/b> <a class=\x27a\x27 href=\x27\/a\/[0-9]{1,}>(.*)<\/a>/, a);
}
}
然后再次使用它
<div>
<b>a:</b> <a class='a' href='/a/1'>a1</a><br>
<b>b:</b> <a class='b' href='/b/2'>b2</a><br>
<b>c:</b> <a class='c' href='/c/3/'>c3</a><br>
<b>d:</b> "ef"<br><br><div class='start'>123
<br>ghij.
<br>klmn
<br><br><b>end</b>
</div>
</div>
并得到輸出
2 0
所以條件if按預期作業,因為<b>a:</b>... 是第二行,但是沒有找到匹配項。這意味著您的正則運算式是錯誤的,經過檢查,您的正則運算式缺少一個單引號,應該是
/^<b>a:<\/b> <a class=\x27a\x27 href=\x27\/a\/[0-9]{1,}\x27>(.*)<\/a>/
然后
{
if ($0 ~ /^<b>a:<\/b> <a class=\x27a\x27/ )
{
print NR, match($0, /^<b>a:<\/b> <a class=\x27a\x27 href=\x27\/a\/[0-9]{1,}\x27>(.*)<\/a>/, a);
print a[1];
}
}
確實給出輸出
2 1
a1
(在 gawk 4.2.1 中測驗)
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/533140.html
標籤:壳awk
