คุณจะลบอักขระ dot ออกจากสตริงโดยไม่เรียกใช้ sed หรือ awk อีกครั้งได้อย่างไร


12

ฉันมีไฟล์ชื่อ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 จะมีโฮสต์ 1,000 แห่งดังนั้นฉันต้องการให้สคริปต์ของฉันเร็วและมีประสิทธิภาพ


2
เหตุผลใดที่dig +shortไม่ได้ผลสำหรับคุณ
Roger Lipscombe

@RogerLipscombe เนื่องจากบางโฮสต์ใน hostlist.txt ของฉันเป็นเพียงชื่อโฮสต์ไม่ใช่ FQDN ดังนั้นฉันจึงใช้ + ค้นหาเพื่อแก้ไขปัญหา
Linoob

คำตอบ:


18

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จะเป็นจริงและคำสั่งในเครื่องหมายปีกกาจะถูกดำเนินการ ครั้งแรกจะลบช่วงเวลาต่อท้ายออกจากสนามแรก วินาทีพิมพ์ฟิลด์แรกตามด้วย,ตามด้วยฟิลด์สุดท้าย คำสั่งที่สามตั้งค่าใหม่fเป็นศูนย์ (เท็จ)

    ในคำอื่น ๆfที่นี่ทำหน้าที่เป็นเงื่อนไขตรรกะ คำสั่งในวงเล็บปีกกาจะถูกดำเนินการถ้าfไม่ใช่ศูนย์ (ซึ่งใน awk หมายถึง 'จริง')

  • /ANSWER SECTION/{f=1}

    หากบรรทัดปัจจุบันมีสตริงANSWER SECTIONดังนั้นตัวแปรfจะถูกตั้งค่าเป็น1(จริง)

    ที่นี่/ANSWER SECTION/ทำหน้าที่เป็นเงื่อนไขเชิงตรรกะ ANSWER SECTIONมันประเมินจริงถ้าปัจจุบันตรงกับการแสดงออกปกติ หากเป็นเช่นนั้นคำสั่งในเครื่องหมายปีกกาจะถูกเรียกใช้งาน


ขอบคุณ @ John1024! ฉันไม่ทราบว่า awk ไม่จำเป็นต้องอยู่ในลูป (ฉันคิดว่ามันจะทำเฉพาะในบรรทัดสุดท้ายหากมันอยู่ข้างนอก) คือfตัวแปรโดยพลการหรือเป็นf{}ส่วนหนึ่งของการทำงานอย่างชัดเจน awk หรือไม่?
Linoob

ยินดีต้อนรับ. fเป็นตัวแปรที่กำหนดเอง คุณสามารถใส่ก่อน{}เงื่อนไขตรรกะที่ซับซ้อน fเป็นเพียงเงื่อนไขตรรกะที่ง่ายมาก: มันเป็นจริงถ้าไม่ใช่ศูนย์เท็จถ้าเป็นศูนย์
John1024

@Linoob โปรดทราบว่าในคำสั่งที่สอง/ANSWER SECTION/มีบทบาทของเงื่อนไขเชิงตรรกะคล้ายกับบทบาทที่fเล่นในคำสั่งแรก ฉันได้อัปเดตคำตอบเพื่อหารือเกี่ยวกับเรื่องนี้
John1024

7

digสามารถอ่านไฟล์ที่มีรายการชื่อโฮสต์และดำเนินการทีละชื่อ คุณสามารถบอกdigให้หยุดการแสดงผลทั้งหมดยกเว้นส่วนคำตอบ

สิ่งนี้จะให้ผลลัพธ์ที่คุณต้องการ:

dig -f hostlist.txt +noall +answer +search | 
    awk '{sub(/\.$/,"",$1); print $1","$5}'

awkของsub()ฟังก์ชั่นที่ใช้ในการตัดช่วงเวลาที่แท้จริง.จากจุดสิ้นสุดของสนามแรก จากนั้นawkพิมพ์ฟิลด์ 1 และ 5 คั่นด้วยเครื่องหมายจุลภาค

หมายเหตุ: รายการhostlist.txtที่ไม่แก้ไขจะถูกยกเลิกอย่างสมบูรณ์ - รายการเหล่านั้นจะไม่ปรากฏใน stdout หรือ stderr

(ทดสอบบน Linux และ FreeBSD)


6

เปลี่ยนการร้องขอของคุณgawkเป็นสิ่งต่อไปนี้:

| gawk '{print substr($1,1,length($1)-1)","$NF}' >fqdn-ip.csv
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.