用awk

2016-01-22 38 views
0

這裏打印的文本塊,直到第一個空行是我的示例文件:用awk

Host dns2 
     HostName 172.20.4.80 
     User root 
     Port 22 

Host dns1 
     HostName 172.20.4.75 
     User root 
     Port 22 

Host dns3 
     HostName 172.20.4.76 
     User root 
     Port 22 

Host dns4 
     HostName 172.20.4.77 
     User root 
     Port 22 

Host dns5 
     HostName 172.20.4.78 
     User root 
     Port 22 

Host dns6 
     HostName 172.20.4.79 
     User root 
     Port 22 

我想打印僅一個街區,是指例如

Host dns1 
     HostName 172.20.4.75 
     User root 
     Port 22 

輸出:

Host: dns2 HostName: 172.20.4.80 User: root Port: 22 

但在這個例子中所有塊有4行,也許他們到達5行或更多行後,所以我想從主機打印到第一空白林E或從主機中刪除,以第一個空行

IM非常糟糕的正則表達式,並需要用它來完成我的劇本

謝謝

+0

你想匹配每個b鎖?^Host \ sdns \ d +(?:\ s + \ w + \ s [\ w \。] +)+ – Aferrercrafter

+1

謝謝我添加了我想要的輸出 –

回答

2

類似awk

$ awk -v RS= -v OFS=' ' '{for(i=1;i<NF;i+=2) $i=$i":"}1' hosts 

Host: dns2 HostName: 172.20.4.80 User: root Port: 22 
Host: dns1 HostName: 172.20.4.75 User: root Port: 22 
Host: dns3 HostName: 172.20.4.76 User: root Port: 22 
Host: dns4 HostName: 172.20.4.77 User: root Port: 22 
Host: dns5 HostName: 172.20.4.78 User: root Port: 22 
Host: dns6 HostName: 172.20.4.79 User: root Port: 22 

會給你在所需的輸出格式中的所有記錄。您可以進一步篩選可以在本輸出或添加這樣的圖案,

$ awk -v RS= -v OFS=' ' '{for(i=1;i<NF;i+=2) $i=$i":"} /dns2/' hosts 

Host: dns2 HostName: 172.20.4.80 User: root Port: 22 

如果要處理所選記錄後退出,你需要稍微改變腳本

$ awk -v RS= -v OFS=' ' '/dns2/{for(i=1;i<NF;i+=2) $i=$i":"; print; exit}' hosts 
Host: dns2 HostName: 172.20.4.80 User: root Port: 22 

如果你想選擇的一切除了一個記錄,你可以否定的模式(和刪除出口)

$ awk -v RS= -v OFS=' ' '!/dns2/{for(i=1;i<NF;i+=2) $i=$i":"; print}' hosts 
Host: dns1 HostName: 172.20.4.75 User: root Port: 22 
Host: dns3 HostName: 172.20.4.76 User: root Port: 22 
Host: dns4 HostName: 172.20.4.77 User: root Port: 22 
Host: dns5 HostName: 172.20.4.78 User: root Port: 22 
Host: dns6 HostName: 172.20.4.79 User: root Port: 22 

注意sed的就地更換需要一箇中間文件。 設置OFS將改變字段之間所有的分隔符:如果你想用一個格式化SANS一個記錄,以替換原文件,你可以在最後的awk語句

$ awk ... > temp && mv temp original 

UPDATE使用此命令模式。你想通過name: value邏輯組他們,所以改變腳本這樣

$ awk -v RS= '{for(i=1;i<NF;i++) $i=$i (i%2?":":"\t")}1' hosts 
Host: dns2  HostName: 172.20.4.80 User: root  Port: 22 
Host: dns1  HostName: 172.20.4.75 User: root  Port: 22 
Host: dns3  HostName: 172.20.4.76 User: root  Port: 22 
Host: dns4  HostName: 172.20.4.77 User: root  Port: 22 
Host: dns5  HostName: 172.20.4.78 User: root  Port: 22 
Host: dns6  HostName: 172.20.4.79 User: root  Port: 22 

這臺甚至定位場後一個選項卡分隔符。

+1

非常感謝您能給sed命令刪除這個塊嗎?例如刪除dns2 –

+0

您不需要'sed',使用'awk'您可以輕鬆地選擇其他記錄。查看更新。 – karakfa

+1

你的意思是我使用awk選擇除該行之外的所有內容並重新定向到該文件? –

3

我認爲你基本上要這樣:

awk -v RS='' '/dns1/' file 

取消設置記錄分隔符,以便將每個塊視爲記錄,然後打印與記錄模式相匹配的記錄。

或者用一個shell變量:

host=dns1 
awk -v host="$host" -v RS='' '$0 ~ host' file 

在這兩個例子中,我使用的事實,默認動作是{ print }。由於您可能會通過使用來更改輸出,因此您可能需要考慮添加exit語句以避免不必要地處理文件的其餘部分。

+1

謝謝你的作品,但你可以修改命令來顯示我想要的輸出嗎? –

+0

您可以在awk腳本的末尾添加一個塊,比如'{printf'%s%s',$ 1,$ 2}',並且可以隨時使用它。 –

+1

我用{print($ 1〜/^Host $ /?「」:「\ t」)$ 1「:」$ 2},但不幸的是不能使用printf「%s%s」 ,$ 1,$ 2}請你幫忙,給我一個sed命令來刪除? –

0

這可能會爲你工作(GNU SED):

sed -n '/Host dns1/{:a;N;/^\s*$/M!ba;s/\n\s*/ /g;s/\s*$//p}' file 

這集中在所要求的字符串,然後追加以下行,直到空白的最後操縱所收集到所需要的輸出新的字符串。

+1

sed:1:「/主機dns1/{:a; N;/^ \ s * $ ...」:意外的EOF(等待)')這是錯誤使用sed在Mac上 –

+1

你的命令中的「M」是什麼意思? –

1

比湯姆·費內奇的做法沒有什麼不同,因爲它使用的記錄分隔符,但它與字段分隔扮演過以獲得所需的輸出:

awk -v RS='' -F'\n[\t ]*' -v OFS=' ' '/dns1/{$1=$1;print}' file 

當您更改輸出字段分隔符,你需要使用$1=$1(或$0=$0或與任何其他字段)強制awk重新評估記錄並考慮新的字段分隔符。

注意:當使用exit命令找到匹配塊時,可以退出awk。這避免了處理文件的所有結尾。 您也只能用第一個字段測試/dns1/的模式。

awk -v RS='' -F'\n[\t ]*' -v OFS=' ' '$1~/dns1/{$1=$1;print;exit}' file 

如果添加分號的結果,因爲您修改字段時,$1=$1伎倆變得無用。你可以寫:

awk -v RS='' -F'\n[\t ]*' -v OFS=' ' '$1~/dns1/{for(i=1;i<=NF;i++){sub(" ", ": ", $i)};print;exit}' file 
+1

非常感謝你迄今爲止最接近的答案,如果我想用我想要的輸出打印所有行,只需要2件事我該怎麼辦?第二你可以請給我sed命令刪除塊嗎? –

+1

僅供參考不在'-v'和變量名之間加一個空格使腳本特定於gawk,所以你應該聲明或者只是在那裏放置一個空間,所以它不是特定於gawk的。 –

1

要打印第3個記錄:

$ awk -v RS= -F'\n[[:blank:]]+' -v OFS='\t' 'NR==3{$1=$1; gsub(/ +/,": "); print}' file 
Host: dns3  HostName: 172.20.4.76 User: root  Port: 22 

打印包含dns4記錄:

$ awk -v RS= -F'\n[[:blank:]]+' -v OFS='\t' '/dns4/{$1=$1; gsub(/ +/,": "); print}' file 
Host: dns4  HostName: 172.20.4.77 User: root  Port: 22 

要打印的所有記錄,除了那些包含dns3dns4,或dns5

$ awk -v RS= -F'\n[[:blank:]]+' -v OFS='\t' '!/dns[345]/{$1=$1; gsub(/ +/,": "); print}' file 
Host: dns2  HostName: 172.20.4.80 User: root  Port: 22 
Host: dns1  HostName: 172.20.4.75 User: root  Port: 22 
Host: dns6  HostName: 172.20.4.79 User: root  Port: 22