IPv6 주소를 추출하라는 명령을 받았습니다.
/usr/bin/ip a | grep inet6 | grep -vE 'fe80|host' | sed -e 's/^.*inet6 \([^ ]*\)\/.*$/\1/;t;d'
sed
교체품을 분해하는 데 도움을 줄 수 있는 사람이 있나요 ?
sed 명령을 사용할 수 없습니다;t;d
답변1
뭔가를 배우고 싶은 것 같은데, 고맙습니다. Symcbean sed
이 명령을 설명하지만 코드에서 배울 수 있는 몇 가지 사항을 더 추가하고 싶었습니다. 나쁜 습관을 피하는 법을 배울 수 있습니다. (-;
- 전체 명령은 두 개의 s와 하나의 를 통해
grep
파이프되며sed
이는 거의 항상 의미가 없습니다. 당신 은sed
할 수 있습니다주소줄만 바꾸는grep
것과 동일한 기능을 동적으로 수행하는 정규 표현식을 접두사로 붙여서 줄을 바꿉니다 . 따라서 '/inet6/!d'는 ( ) 없이 모든 줄을 삭제할 수 있으며 두 번째 줄을 ( 또는 확장 정규식 옵션: ) 으로 바꿀 수 있습니다 .sed -n '/foo/s/pattern/replace/p'
foo
!
inet6
grep
/fe80/d;/host/d
-E
/fe08|host/d
-e
명령이 하나만 있는 경우(또는 여러 명령이 연결된 경우) 선택 사항입니다;
. 초과분을 제거하면 내용을 읽기가 더 쉬워집니다.- 이미 지적했듯이 정규식을
^.*
. 욕심 많은 사람들은*
어차피 처음부터 무엇이든 어울릴 테니 불필요한 닻으로 독자의 주의를 산만하게 하지 마세요. .*$
마지막 에도 마찬가지입니다 . 앵커를 제거합니다.- 패턴에 슬래시가 포함되어 있으면
s
명령에 다른 구분 기호를 사용하십시오. 거의 모든 문자가 허용되는데 왜 백슬래시를 채워서 표현식을 읽기 어렵게 만들까요? 밑줄은 좋은 선택입니다. 예를 들면 다음과 같습니다.s_.*inet6 \([^ ]*\)/.*_\1_
\(…\)
and를 사용하면\1
유용할 수 있지만, 중간 부분만 추출하는 것이라면 시작과 끝을 별도로 제거하는 것이 더 포괄적일 수 있습니다.s/.*inet6 //;s_/.*__
- 정의 에 따르면
sed
명령 뒤에는 선택적으로 점프 표시가 따라오는데, 이 경우가 그렇습니다t
.;d
흔하지는 않지만 합법적입니다. GNU 버전에서는sed
점프 태그에 세미콜론을 허용하지 않지만 이를 명령 구분 세미콜론으로 해석합니다. 이 경우 "대체가 이루어지면 스크립트 끝으로 점프"라는 의미의 점프 마커가 없습니다. 하지만 다른sed
버전에서는 오류가 발생합니다. 이런 세부 사항과 호환되지 않는 스크립트가 있다는 것은 정말 역겨운 일입니다! 예를 들어 별도의 스크립트를 사용하면 이 문제를 피할 수 있습니다-e '…;t' -e d
. 또는 새 줄에 명령을 작성하면 됩니다. t;d
이 경우 대체가 실패하면 출력이 복잡해지는 것을 방지하는 것이 아이디어 입니다. 좋은 생각이지만, 이를 달성하기 위한 실제 도구가 있습니다. 바로 다음 명령p
의 플래그 입니다s
.s_.*inet6 \([^ ]*\)/.*_\1_p;d
교체한 경우p
버퍼를 플러시합니다. 읽기 쉽고 휴대하기 쉽습니다.- 후행
d
명령은 기본 출력을 억제하는 옵션으로 대체될 수 있지만-n
이는 취향의 문제입니다.
마지막으로 명령을 비교할 수 있습니다
/usr/bin/ip a | grep inet6 | grep -vE 'fe80|host' | sed -e 's/^.*inet6 \([^ ]*\)\/.*$/\1/;t;d'
/usr/bin/ip a | sed '/inet6/!d; /fe80/d; /host/d; s/.*inet6 //; s_/.*__p; d'
또는 -n
대신 ERE를 사용하십시오 d
.
/usr/bin/ip a | sed -En '/inet6/!d; /fe80|host/d ;s/.*inet6 //; s_/.*__p'
골퍼가 작성할 수 있는 코드
sed -En '/fe80|host/!s_.*inet6 ([^ ]*)/.*$_\1_p'
그러나 이것은 나에게 읽기 쉬운 것 같지 않습니다.
답변2
먼저 표현을 좀 단순화하겠습니다.
LINE=" inet6 fd86:73ea:ff6b:0:141b:ca40:741b:ec0c/64 scope global noprefixroute"
echo $LINE | sed -e' s/^.*inet6 \([^ ]*\)\/.*$/\1/;t;d'
이것-이자형다음 매개변수는 sed 스크립트라는 의미입니다.
's/pattern/replace/'는 입력에서 "패턴"을 찾아 "교체"로 바꾸는 것을 의미합니다.
여기의 패턴은/^.*inet6 \([^ ]*\)\/.*$/
'/'는 패턴의 시작과 끝을 표시합니다.
^ 및 $ 문자는 각각 입력 문자열의 시작과 끝과 항상 일치합니다. 입력 문자열에는 항상 시작과 끝이 있다는 점에 유의하세요. 이는 이러한 위치를 기준으로 요소를 일치시키거나 교체하려는 경우에 유용합니다.
.*
임의의 문자가 0개 이상 발생함을 나타냅니다. 위의 $LINE에서는 단일 공백 문자와 일치합니다.
inet6
리터럴 문자열 "inet6"(후행 공백 포함)을 나타냅니다.
괄호는 \(pattern\)
sed에게 입력의 하위 패턴을 일치시킬 뿐만 아니라 나중에 사용할 수 있도록 저장하도록 지시합니다.
평균은 \/
리터럴 "/"와 일치합니다(위 참조 - 접두사가 없으면 "/" 문자는 패턴의 구조적 요소를 나타냅니다).
.*$
줄 끝까지 남은 문자를 일치시키는 것을 의미합니다.
/
모드 종료를 표시합니다.
\1
이것이 교체입니다. 여기서 1은 패턴으로 찾은 첫 번째로 저장된 일치 항목을 나타냅니다(단, 하나만 해당).