[英]Print a block of text until the first blank line using 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行或更多行,所以我想從主機打印到第一行或從主機刪除到第一行
我真的對正則表達式不好,需要這個來完成我的腳本
謝謝
我認為您基本上想要這樣:
awk -v RS='' '/dns1/' file
取消設置記錄分隔符,以便將每個塊都視為一條記錄,然后打印與模式匹配的任何記錄。
或使用shell變量:
host=dns1
awk -v host="$host" -v RS='' '$0 ~ host' file
在這兩個示例中,我都使用默認操作為{ print }
的事實。 由於您可能會使用{ printf ... }
來更改輸出,因此您可能要考慮添加一個exit
語句,以避免不必要地處理文件的其余部分。
類似的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就地替換需要一個中間文件。 如果要將原始文件替換為無一個記錄的格式化文件,則可以在最后一個awk語句上使用此命令模式
$ awk ... > temp && mv temp original
更新:設置OFS
將更改字段之間的所有分隔符。 您想按name: value
邏輯對它們進行分組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
在偶數定位的字段之后設置制表符分隔符。
與Tom Fenech的方法沒有什么不同,因為它使用記錄分隔符,但是它也與字段分隔符一起使用以獲得所需的輸出:
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
要打印第三條記錄:
$ 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
要打印所有包含dns3
, dns4
或dns5
記錄,請dns4
以下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
這可能對您有用(GNU sed):
sed -n '/Host dns1/{:a;N;/^\s*$/M!ba;s/\n\s*/ /g;s/\s*$//p}' file
這將重點放在所需的字符串上,然后追加以下幾行直到空白為止,最后操作收集到所需輸出中的新字符串。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.