가장 쉬운 것은 아니지만 다음과 같이 할 수 있습니다.
$ IP=109.96.77.15
$ echo "$((${-+"(${IP//./"+256*("}))))"}&255))"
109
$ echo "$((${-+"(${IP//./"+256*("}))))"}>>8&255))"
96
$ echo "$((${-+"(${IP//./"+256*("}))))"}>>16&255))"
77
$ echo "$((${-+"(${IP//./"+256*("}))))"}>>24&255))"
15
(그 곳이 경우 ksh93에서 작동합니다 ${var//pattern/replacement}
연산자에서 유래), bash
4.3, 비지 박스 sh
, yash
, mksh
과 zsh
, 물론 있지만 에서 zsh
, 훨씬 간단 방법이 있습니다 . 의 이전 버전에서는 bash
내부 따옴표를 제거해야합니다. ksh93이 아닌 대부분의 다른 쉘에서도 제거 된 내부 인용 부호와 함께 작동합니다.
$IP
IPv4 주소의 유효한 십진수 표현이 포함되어 있다고 가정 합니다 (그러나 0x6d.0x60.0x4d.0xf
일부 쉘의 경우 8 진수와 같은 16 진수 표현에도 작동 하지만 값을 10 진수로 출력 함). 내용이 $IP
신뢰할 수없는 출처에서 온 경우 이는 명령 삽입 취약점에 해당합니다.
기본적으로, 우리는 모든 대체하고 같은 .
에 $IP
로 +256*(
, 우리는 평가 결국 :
$(( (109+256*(96+256*(77+256*(15))))>> x &255 ))
우리는 IPv4 주소와 같은 그 4 바이트에서 32 비트 정수를 구성하고 그래서 궁극적으로 (바이트 반전 생각에)입니다 ¹ 한 후 사용하여 >>
, &
관련 바이트를 추출하는 비트 연산자.
우리는 사용 ${param+value}
(여기에 표준 연산자를 $-
대신으로 항상 설정이 보장되는) value
그렇지 않으면 연산 파서가 일치하지 않는 괄호에 대해 불평하기 때문. 여기서 쉘은 폐쇄 찾을 수 ))
개구를 들어 $((
한 후 그 안에 확장 평가하는 연산 식을 초래할 것이다 수행한다.
로 $(((${IP//./"+256*("}))))&255))
대신 쉘은 두 번째와 세 번째 치료하는 것입니다 )
닫는 거기들 ))
에 대한 $((
및 구문 오류를보고합니다.
ksh93에서는 다음을 수행 할 수도 있습니다.
$ echo "${IP/@(*).@(*).@(*).@(*)/\2}"
96
bash
, mksh
, zsh
의 경우 ksh93의 복사 한 ${var/pattern/replacement}
연산자를하지만 캡처 그룹은 부분을 처리하지 않는 것이. zsh
다른 구문으로 지원합니다.
$ setopt extendedglob # for (#b)
$ echo ${IP/(#b)(*).(*).(*).(*)/$match[2]}'
96
bash
정규 표현식 일치 연산자 에서는 캡처 그룹 처리의 형식을 지원하지만 지원 하지는 않습니다 ${var/pattern/replacement}
.
POSIXly, 당신은 다음을 사용합니다 :
(IFS=.; set -o noglob; set -- $IP; printf '%s\n' "$2")
는 noglob
값 나쁜 놀라움을 피하기 위해 $IP
같은 10.*.*.*
서브 쉘이 옵션에 이러한 변경 사항의 범위를 제한하는, $IFS
.
¹ IPv4 주소는 32 비트 정수이고 127.0.0.1은 가장 일반적인 텍스트 표현 중 하나 일뿐입니다. 루프백 인터페이스의 동일한 일반적인 IPv4 주소는 0x7f000001 또는 127.1 ( 1
127.0 / 8 클래스 A 네트워크 의 주소 라고 말하기에 더 적합 할 수도 있음 ) 또는 0177.0.1 또는 1의 다른 조합으로 표시 될 수 있습니다. 8 진수, 10 진수 또는 16 진수로 표현 된 4 자리 숫자. ping
예를 들어 모든 것을 전달할 수 있으며 모두 로컬 호스트를 핑하는 것을 볼 수 있습니다.
당신은 (여기에 임의의 임시 변수를 설정하는 부작용이 괜찮다면 $n
)에서 bash
또는 ksh93
또는 zsh -o octalzeroes
또는 lksh -o posix
단순히있는 32 비트 정수로 다시 모든 표현을 변환 할 수 있습니다 :
$((n=32,(${IP//./"<<(n-=8))+("})))
그런 다음 위와 같이 >>
/ &
조합으로 모든 구성 요소를 추출하십시오 .
$ IP=0x7f000001
$ echo "$((n=32,(${IP//./"<<(n-=8))+("})))"
2130706433
$ IP=127.1
$ echo "$((n=32,(${IP//./"<<(n-=8))+("})))"
2130706433
$ echo "$((n=32,((${IP//./"<<(n-=8))+("}))>>24&255))"
127
$ perl -MSocket -le 'print unpack("L>", inet_aton("127.0.0.1"))'
2130706433
mksh
산술 표현식에 부호있는 32 비트 정수를 $((# n=32,...))
사용하면 부호없는 32 비트 숫자 ( posix
8 진 상수를 인식 하는 옵션) 를 강제로 사용할 수 있습니다 .
IFS
을 위해read
:이IFS=. read -a ArrIP<<<"$IP"