bash에서 마지막 점 다음에 문자열 바꾸기


12

문자열 (IP 주소)에 다음 패턴이 있습니다.

123.444.888.235

점 뒤의 마지막 숫자를로 바꾸고 싶습니다 0.

123.444.888.0

bash다른 쉘 스크립트 언어로 어떻게 할 수 있습니까?


1
그 줄은 어디에 있습니까? bash 변수에서? 텍스트 파일에서 한 줄에 하나씩?
Stéphane Chazelas

변수에 있습니다. 죄송 합니다만 언급하지 않았습니다.
Ari

3
IP 주소 인 경우 444 및 888은 유효하지 않은 8 진수 값입니다.
디지털 외상

답변:


24

POSIX 쉘에서 :

var=123.444.888.235
new_var="${var%.*}.0"

${var%pattern}ksh80 년대에 도입 된 연산자로 표준 sh언어에 대해 POSIX에 의해 표준화 되었으며 이제를 포함하여 해당 언어를 해석하는 모든 쉘에 의해 구현됩니다 bash.

${var%pattern}의 내용 팽창 $var과 일치하는 가장 짧은 문자열을 박탈 패턴을 그것의 끝 (또는 동일한에로 떨어져 $var그 경우 패턴이 일치하지 않음). 따라서 ${var%.*}( 점 뒤에 임의의 문자 수를 의미 .*하는 패턴 이 있습니다)는 맨 $var오른쪽없이 확장되고 그 뒤에 오는 .것이 무엇입니까? 대조적으로, 패턴과 일치 ${var%%.*}하는 가장 긴 문자열이 제거 되는 위치는 가장$var 왼쪽없이 확장 .되며 그 뒤를 따라갑니다.


무엇입니까 ? ${var%.*}
목소리

@ tjt263의 명령 행 유형에서 man bashenter를 누른 다음 /suffix patternenter를 입력하십시오. :)
와일드 카드

귀하의 게시물에 따옴표를 추가 했습니다 : new_var="${var%.*}.0"... nJoy !.

8

이 작동합니다.

echo 123.444.888.235 | sed 's/\([0-9]*\.[0-9]*\.[0-9]*\.\)[0-9]*/\10/'

마지막 sed대체 필드 \10인는 첫 번째로 일치하는 패턴 ( \1)이며 리터럴 0으로 연결됩니다.


5

몇 가지 방법 (이들 모두는 문자열에서 마지막 숫자 세트를 변경한다고 가정합니다) :

$ echo 123.444.888.235 | awk -F'.' -vOFS='.' '{$NF=0}1;'
123.444.888.0

여기에서는 입력 필드 구분 기호 로 사용하고 출력 필드 구분 기호 로 사용하도록 -F'.'지시 awk합니다 . 그런 다음, 우리는 단순히 마지막 필드를 (설정 0)과 (선을 인쇄 입니다 속기는 "현재 행을 인쇄"를)..-vOFS='.'$NF1;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

5

넷 마스크를 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이 예제에서는 대신 사용 했습니다.


0

다른 sed답변 :

sed -r 's/(.*\.).*/\10/'

모든 것을 마지막 점까지 그룹화하고 전체 행을 그룹의 내용과 그 뒤에 0으로 바꿉니다
. 괄호를 이스케이프 처리하지 않으려면 -r을 사용하십시오.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.