Shell-Script

如何在不再次呼叫 sed 或 awk 的情況下從字元串中刪除點字元?

  • May 26, 2016

我有一個名為的文件hostlist.txt,其中包含如下文本:

host1.mydomain.com
host2.mydomain.com
anotherhost
www.mydomain.com
login.mydomain.com
somehost
host3.mydomain.com

我有以下小腳本:

#!/usr/local/bin/bash

while read host; do
       dig +search @ns1.mydomain.com $host ALL \
       | sed -n '/;; ANSWER SECTION:/{n;p;}';
done <hostlist.txt \
       | gawk '{print $1","$NF}' >fqdn-ip.csv

輸出到fqdn-ip.csv

host1.mydomain.com.,10.0.0.1
host2.mydomain.com.,10.0.0.2
anotherhost.internal.mydomain.com.,10.0.0.11
www.mydomain.com.,10.0.0.10
login.mydomain.com.,10.0.0.12
somehost.internal.mydomain.com.,10.0.0.13
host3.mydomain.com.,10.0.0.3

我的問題是如何在呼叫或再次刪除.逗號之前刪除?我可以在現有或呼叫中執行一個步驟來去除點嗎?sed``gawk``sed``gawk

hostlist.txt將包含 1000 台主機,所以我希望我的腳本快速高效。

sed命令、命令awk和尾隨句點的刪除都可以組合成一個 awk 命令:

while read -r host; do dig +search "$host" ALL; done <hostlist.txt | awk 'f{sub(/.$/,"",$1); print $1", "$NF; f=0} /ANSWER SECTION/{f=1}'

或者,分佈在多行:

while read -r host
do
   dig +search "$host" ALL
done <hostlist.txt | awk 'f{sub(/.$/,"",$1); print $1", "$NF; f=0} /ANSWER SECTION/{f=1}'

因為awk命令跟在done語句後面,所以只awk呼叫了一個程序。儘管在這裡效率可能無關緊要,但這比在每個循環中創建一個新的 sed 或 awk 程序更有效。

例子

使用此測試文件:

$ cat hostlist.txt 
www.google.com
fd-fp3.wg1.b.yahoo.com

該命令產生:

$ while read -r host; do dig +search "$host" ALL; done <hostlist.txt | awk 'f{sub(/.$/,"",$1); print $1", "$NF; f=0} /ANSWER SECTION/{f=1}'
www.google.com, 216.58.193.196
fd-fp3.wg1.b.yahoo.com, 206.190.36.45

這個怎麼運作

awk 一次隱式讀取其輸入一條記錄(行)。此 awk 腳本使用單個變數 ,f它表示上一行是否是答案部分標題。

  • f{sub(/.$/,"",$1); print $1", "$NF; f=0}

如果前一行是答案部分標題,f則為 true,並且執行大括號中的命令。第一個從第一個欄位中刪除尾隨句點。第二個列印第一個欄位,然後是,,然後是最後一個欄位。第三條語句重置f為零(假)。

換言之,f這裡作為一個邏輯條件起作用。f如果非零(在 awk 中表示“真”),則執行大括號中的命令。

  • /ANSWER SECTION/{f=1}

如果目前行包含字元串ANSWER SECTION,則變數f設置為1(true)。

在這裡,/ANSWER SECTION/作為一個邏輯條件。如果目前匹配正則表達式,它的計算結果為真ANSWER SECTION。如果是,則執行大括號中的命令。

引用自:https://unix.stackexchange.com/questions/285525