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 1000 개의 호스트를 포함하므로 스크립트가 빠르고 효율적이기를 원합니다.


2
dig +short당신을 위해 작동하지 않는 이유 가 있습니까?
Roger Lipscombe

@RogerLipscombe 내 hostlist.txt의 일부 호스트는 FQDN이 아닌 호스트 이름이므로 + search를 사용하여 문제를 해결하고 있습니다.
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경우 true가되고 중괄호 안의 명령이 실행됩니다. 첫 번째는 첫 번째 필드에서 후행을 제거합니다. 두 번째는 첫 번째 필드, 그 ,뒤에, 마지막 필드를 인쇄합니다 . 세 번째 명령문 f은 0으로 재설정 됩니다 (false).

    다시 말해, f여기서 논리적 조건으로 작동합니다. 중괄호 안의 명령 f은 0이 아닌 경우 실행됩니다 (awk에서는 'true'를 의미 함).

  • /ANSWER SECTION/{f=1}

    현재 행에 string이 포함 된 ANSWER SECTION경우 변수 f1(true)로 설정됩니다 .

    여기서 /ANSWER SECTION/논리적 조건으로 사용됩니다. 전류가 정규식과 일치하면 true로 평가됩니다 ANSWER SECTION. 그렇다면 중괄호 안의 명령이 실행됩니다.


@ John1024 감사합니다! 나는 awk가 루프 안에있을 필요가 없다는 것을 몰랐다 (나는 그것이 외부에 있다면 마지막 줄에서만 작용할 것이라고 생각했다). 가 f임의의 변수 또는이다 f{}AWK의 기능을 명시 적 부분?
Linoob

천만에요. f임의의 변수입니다. {}복잡한 논리 조건 앞에 놓을 수 있습니다 . f매우 간단한 논리 조건입니다. 0이 아닌 경우 true, 0이면 false입니다.
John1024

@Linoob 두 번째 명령 에서 첫 번째 명령에서 /ANSWER SECTION/수행 된 역할과 유사한 논리 조건의 역할을합니다 f. 이에 대한 답변을 업데이트했습니다.
John1024

7

dig호스트 이름 목록이 포함 된 파일을 읽고 하나씩 처리 할 수 ​​있습니다. dig답변 섹션을 제외한 모든 출력을 억제하도록 지시 할 수도 있습니다 .

원하는 결과를 얻을 수 있습니다.

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

awksub()함수는 .첫 번째 필드 끝에서 리터럴 기간을 제거하는 데 사용됩니다 . 그런 다음 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.