Sed veya awk çağırmadan nokta karakterini dizeden nasıl kaldırırsınız?


12

Ben böyle bir hostlist.txtmetin içeren adlı bir dosya var :

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

Aşağıdaki küçük komut dosyası var:

#!/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

Hangi çıktılar 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

Sorum nasıl silerim olduğunu .hemen önce virgül olmadan çağırma sedveya gawkyeniden? Mevcut sedveya gawkçağrılarda noktayı kaldıracak bir adım var mı ?

hostlist.txt 1000'ler barındırılacak, bu yüzden betiğimin hızlı ve verimli olmasını istiyorum.


2
dig +shortSizin için neden çalışmadığının herhangi bir nedeni var mı?
Roger Lipscombe

@RogerLipscombe çünkü benim hostlist.txt bazı ana bilgisayarlar sadece FNDN değil, ana bilgisayar adları, bu yüzden onları çözmek için + arama kullanıyorum.
Linoob

Yanıtlar:


18

sedKomut, awkkomut ve arka süre kaldırılması tek bir awk komut birleştirilebilir:

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}'

Veya birden çok satıra yayıldıkça:

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}'

Çünkü awkkomut aşağıdaki donedeyimi, yalnızca bir awkişlem çağrılır. Her ne kadar verimlilik burada önemli olmasa da, bu her döngüde yeni bir sed veya awk işlemi oluşturmaktan daha etkilidir.

Misal

Bu test dosyasıyla:

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

Komut şunu üretir:

$ 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

Nasıl çalışır

awk, girdisini her seferinde bir kayıt (satır) örtülü olarak okur. Bu awk betiği f, önceki satırın bir yanıt bölümü üstbilgisi olup olmadığını gösteren tek bir değişken kullanır .

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

    Önceki satır bir yanıt bölümü üstbilgisiyse, fdoğru olur ve süslü parantez içindeki komutlar yürütülür. Birincisi, izleyen dönemi ilk alandan kaldırır. İkincisi ilk alanı ve ardından ,son alanı yazdırır . Üçüncü ifade fsıfıra (yanlış) sıfırlanır .

    Başka bir deyişle, fburada mantıklı bir koşul olarak işlev görür. Kıvırcık parantez içindeki komutlar fsıfır değilse çalıştırılır (awk olarak 'true' anlamına gelir).

  • /ANSWER SECTION/{f=1}

    Geçerli satır dizeyi içeriyorsa, ANSWER SECTIONdeğişken (true) folarak ayarlanır 1.

    Burada /ANSWER SECTION/mantıklı bir durum olarak hizmet eder. Akım normal ifadeyle eşleşiyorsa doğru olarak değerlendirilir ANSWER SECTION. Varsa, kıvırcık parantez içindeki komut yürütülür.


Teşekkürler @ John1024! Awk'ın döngü içinde olması gerekmediğini bilmiyordum (sadece son satırda dışarıda olsaydı hareket edeceğini düşündüm). Mı fkeyfi değişken veya f{}awk işlevlerden açık bir parçasıdır?
Linoob

Rica ederim. fisteğe bağlı bir değişkendir. Aslında {}karmaşık mantıksal koşulların önüne koyabilirsiniz . fsadece çok basit bir mantıksal durumdur: sıfırdan farklıysa, sıfırsa yanlıştır.
John1024

@Linoob İkinci komutta, ilk komutta oynanan /ANSWER SECTION/role benzer mantıksal koşul rolünü foynadığını unutmayın. Bunu tartışmak için cevabı güncelledim.
John1024

7

digana bilgisayar adlarının listesini içeren bir dosyada okuyabilir ve bunları tek tek işleyebilir. Ayrıca dig, cevap bölümü dışındaki tüm çıktıları gizlemeyi söyleyebilirsiniz .

Bu size istediğiniz çıktıyı vermelidir:

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

awk'nin sub()işlevi, gerçek .alanı ilk alanın sonundan çıkarmak için kullanılır . Ardından, awk1 ve 5 numaralı alanları virgülle ayırarak yazdırır.

NOT: çözülmeyen girdiler hostlist.txttamamen atılır - stdout VEYA stderr'de görünmezler.

(Linux ve FreeBSD üzerinde test edilmiştir)


6

Çağrınızı gawkaşağıdakilerle değiştirin:

| gawk '{print substr($1,1,length($1)-1)","$NF}' >fqdn-ip.csv
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.