문자열 (IP 주소)에 다음 패턴이 있습니다.
123.444.888.235
점 뒤의 마지막 숫자를로 바꾸고 싶습니다 0
.
123.444.888.0
bash
다른 쉘 스크립트 언어로 어떻게 할 수 있습니까?
답변
POSIX 쉘에서 :
var=123.444.888.235
new_var="${var%.*}.0"
${var%pattern}
ksh
80 년대에 도입 된 연산자로 표준 sh
언어에 대해 POSIX에 의해 표준화 되었으며 이제를 포함하여 해당 언어를 해석하는 모든 쉘에 의해 구현됩니다 bash
.
${var%pattern}
의 내용 팽창 $var
과 일치하는 가장 짧은 문자열을 박탈 패턴을 그것의 끝 (또는 동일한에로 떨어져 $var
그 경우 패턴이 일치하지 않음). 따라서 ${var%.*}
( 점 뒤에 임의의 문자 수를 의미 .*
하는 패턴 이 있습니다)는 맨 $var
오른쪽없이 확장되고 그 뒤에 오는 .
것이 무엇입니까? 대조적으로, 패턴과 일치 ${var%%.*}
하는 가장 긴 문자열이 제거 되는 위치는 가장$var
왼쪽없이 확장 .
되며 그 뒤를 따라갑니다.
답변
이 작동합니다.
echo 123.444.888.235 | sed 's/\([0-9]*\.[0-9]*\.[0-9]*\.\)[0-9]*/\10/'
마지막 sed
대체 필드 \10
인는 첫 번째로 일치하는 패턴 ( \1
)이며 리터럴 0으로 연결됩니다.
답변
몇 가지 방법 (이들 모두는 문자열에서 마지막 숫자 세트를 변경한다고 가정합니다) :
$ echo 123.444.888.235 | awk -F'.' -vOFS='.' '{$NF=0}1;'
123.444.888.0
여기에서는 입력 필드 구분 기호 로 사용하고 출력 필드 구분 기호 로 사용하도록 -F'.'
지시 awk
합니다 . 그런 다음, 우리는 단순히 마지막 필드를 (설정 0)과 (선을 인쇄 입니다 속기는 “현재 행을 인쇄”를)..
-vOFS='.'
$NF
1;
awk
$ echo 123.444.888.235 | perl -pe 's/\d+$/0/'
123.444.888.0
는 -p
지시 perl
에 의해 주어진 스크립트를 적용한 후 각 입력 라인을 인쇄 -e
. 스크립트 자체는 행의 끝에 하나 이상의 숫자를로 바꾸는 간단한 대체 연산자입니다 0
.
$ echo 123.444.888.235 | sed 's/[0-9]*$/0/'
123.444.888.0
에서 대신 sed
사용 [0-9]
하는 동일한 아이디어 입니다 \d
.
문자열이 변수에 있고 여기에서 문자열 을 지원하는 쉘 (예 : bash
또는 zsh
)을 사용하는 경우 위의 내용을 다음과 같이 변경할 수 있습니다.
awk -F'.' -vOFS='.' '{$NF=0}1;' <<<$var
perl -pe 's/\d+$/0/' <<<$var
sed 's/[0-9]*$/0/' <<<$var
답변
넷 마스크를 IP 주소에 적용하는 일반적인 경우 :
입력 내용이 IP 주소이고 해당 주소의 마지막 옥텟을으로 바꾸는 것을 감안할 때 실제로 달성하려는 것은 넷 마스크를 사용하여 IP 주소의 네트워크 부분을 계산하는 .0
것으로 가정 합니다 .255.255.255.0
넷 마스크 길이를 8로 나눌 수있는 경우 단순히 옥텟을 0으로 바꾸는 것이 좋습니다. 그러나 일반적인 경우는 아닙니다. 유효한 (서브넷) 넷 마스크에 대해이 작업을 수행해야하는 경우 다음과 같이 할 수 있습니다.
function d2i() {
echo $(( 0x$( printf "%02x" ${1//./ } ) ))
}
function i2d() {
h=$( printf "%08X" "$1" )
echo $(( 0x${h:0:2} )).$(( 0x${h:2:2} )).$(( 0x${h:4:2} )).$(( 0x${h:6:2} ))
}
function ipmask() {
i2d $(( $( d2i $1 ) & $( d2i $2 ) ))
}
ipmask 123.44.88.235 255.255.255.0 # outputs 123.44.88.0
ipmask 123.44.88.235 255.255.255.240 # outputs 123.44.88.224
이것은 3 가지 기능을 정의합니다 :
d2i()
점으로 구분 된 10 진수 형식의 IP 주소 (또는 마스크)를 간단한 정수로 변환i2d()
반대로-간단한 정수를 점으로 된 십진수로 변환ipmask()
단순히 주소와 네트워크 마스크의 비트 단위 AND를 계산하여 주소의 네트워크 부분을 제공합니다. Bash는 피연산자&
가 정수일 것으로 예상합니다 .
ipmask
두 개의 다른 마스크에 대한 IP 주소에서 네트워크를 계산하는 방법 을 보여주기 위한 두 번의 호출 .
질문에 명시된대로 123.444.888.235
유효하지 않은 IP 주소입니다. 123.44.88.235
이 예제에서는 대신 사용 했습니다.
답변
다른 sed
답변 :
sed -r 's/(.*\.).*/\10/'
모든 것을 마지막 점까지 그룹화하고 전체 행을 그룹의 내용과 그 뒤에 0으로 바꿉니다
. 괄호를 이스케이프 처리하지 않으려면 -r을 사용하십시오.