Mam następujący ciąg w ciągu (adres IP):
123.444.888.235
Chcę zastąpić ostatni numer po kropce 0, więc staje się:
123.444.888.0
Jak mogę to zrobić w bashinnym języku skryptowym powłoki?
Mam następujący ciąg w ciągu (adres IP):
123.444.888.235
Chcę zastąpić ostatni numer po kropce 0, więc staje się:
123.444.888.0
Jak mogę to zrobić w bashinnym języku skryptowym powłoki?
Odpowiedzi:
W dowolnej powłoce POSIX:
var=123.444.888.235
new_var="${var%.*}.0"
${var%pattern}jest operatorem wprowadzonym kshw latach 80., znormalizowanym przez POSIX dla standardowego shjęzyka i teraz zaimplementowanym przez wszystkie powłoki, które interpretują ten język, w tym bash.
${var%pattern}rozwija się do zawartości $varpozbawionego najkrótszego łańcucha, który pasuje do wzorca na jego końcu (lub do tego samego, $varjakby ten wzór nie pasował). Tak więc ${var%.*}(gdzie .*jest wzorzec oznaczający kropkę, po której następuje dowolna liczba znaków) rozwija się $varbez znaku najbardziej po prawej .i co następuje po nim. W przeciwieństwie do tego, ${var%%.*}gdy najdłuższy ciąg pasujący do wzoru zostanie rozebrany, rozwinąłby się $varbez skrajnego lewego .i tego, co następuje po nim.
${var%.*}
man bashi naciśnij enter, następnie wpisz /suffix patterni naciśnij enter. :)
new_var="${var%.*}.0"... nJoy !.
Kilka sposobów (wszystkie zakładają, że chcesz zmienić ostatni zestaw liczb w ciągu):
$ echo 123.444.888.235 | awk -F'.' -vOFS='.' '{$NF=0}1;'
123.444.888.0
Tutaj -F'.'mówi, awkaby użyć .jako separatora pola wejściowego i -vOFS='.'użyć go jako separatora pola wyjściowego. Następnie po prostu ustawiamy ostatnie pole ( $NF) na 0 i wypisujemy linię ( 1;to awkskrót od „print the current line”).
$ echo 123.444.888.235 | perl -pe 's/\d+$/0/'
123.444.888.0
-pMówi perlwydrukować każdą linię wejściowego po zastosowaniu skryptu podane przez -e. Sam skrypt jest po prostu prostym operatorem podstawiania, który zastąpi jedną lub więcej liczb na końcu wiersza 0.
$ echo 123.444.888.235 | sed 's/[0-9]*$/0/'
123.444.888.0
Ten sam pomysł w sed, używając [0-9]zamiast \d.
Jeśli twój ciąg jest w zmiennej i używasz powłoki, która obsługuje tutaj ciągi (takie jak bashlub zshna przykład), możesz zmienić powyższe na:
awk -F'.' -vOFS='.' '{$NF=0}1;' <<<$var
perl -pe 's/\d+$/0/' <<<$var
sed 's/[0-9]*$/0/' <<<$var
Biorąc pod uwagę, że wpisujesz adres IP i zastępujesz ostatni oktet tego adresu .0, zakładam, że naprawdę próbujesz obliczyć część sieciową adresu IP za pomocą 255.255.255.0maski sieci.
Zwykłe zastąpienie oktetów zerami jest OK, jeśli długość maski sieci jest podzielna przez 8, ale nie jest to ogólny przypadek. Jeśli kiedykolwiek będziesz musiał wykonać tę operację dla dowolnej prawidłowej maski sieci (podsieci), możesz zrobić coś takiego:
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
Definiuje to 3 funkcje:
d2i() konwertuje kropkowo-dziesiętną postać adresu IP (lub maski) na prostą liczbę całkowitąi2d() robi coś przeciwnego - konwertuje zwykłą liczbę całkowitą na kropkę dziesiętnąipmask()po prostu oblicza bitowo ORAZ adresu i maski sieci, aby podać część adresu w sieci. Bash oczekuje, że operandy &będą liczbami całkowitymi.Dwa połączenia ipmaskpokazują, jak można obliczyć sieć z adresu IP dla dwóch różnych masek.
Uwaga: jak podano w pytaniu, 123.444.888.235to nieprawidłowy adres IP. Użyłem 123.44.88.235zamiast tego dla tych przykładów.