ฉันมีรูปแบบต่อไปนี้ในสตริง (ที่อยู่ IP):
123.444.888.235
ฉันต้องการแทนที่หมายเลขสุดท้ายหลังจากจุดด้วย0ดังนั้นมันจะกลายเป็น:
123.444.888.0
ฉันจะทำในbashภาษาสคริปต์ภาษาอื่นได้อย่างไร
ฉันมีรูปแบบต่อไปนี้ในสตริง (ที่อยู่ 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 มาตรฐานโดย POSIX สำหรับมาตรฐานภาษาและขณะนี้ดำเนินการโดยเปลือกหอยทุกสิ่งที่ตีความภาษาที่รวมทั้งshbash
${var%pattern}ขยายไปยังเนื้อหาของการ$varปล้นของสตริงที่สั้นที่สุดที่ตรงกับรูปแบบปิดท้ายของมัน (หรือเหมือนกับ$varว่ารูปแบบนั้นไม่ตรงกัน) ดังนั้น${var%.*}(ซึ่ง.*เป็นรูปแบบที่หมายถึงจุดตามด้วยจำนวนอักขระใด ๆ ) จะขยายออกไป$varโดยไม่ต้องใช้ขวาสุด.และสิ่งที่ตามมา ในทางตรงกันข้าม${var%%.*}ที่ยาวที่สุดสตริงที่ตรงกับรูปแบบที่มีการปล้นจะขยายตัวออกไป$varโดยไม่ต้องซ้ายมากที่สุด.และสิ่งที่ตามมา
${var%.*}
man bashและกด Enter จากนั้นพิมพ์/suffix patternและกด Enter :)
new_var="${var%.*}.0"... nJoy!
สิ่งนี้น่าจะใช้ได้
echo 123.444.888.235 | sed 's/\([0-9]*\.[0-9]*\.[0-9]*\.\)[0-9]*/\10/'
โปรดทราบว่าเขตข้อมูลสุดท้ายของการsedทดแทน, \10เป็นรูปแบบที่ตรงกันครั้งแรก ( \1), ตัดแบ่งด้วยศูนย์ตัวอักษร
สองสามวิธี (สิ่งเหล่านี้ถือว่าคุณต้องการเปลี่ยนตัวเลขชุดสุดท้ายในสตริง):
$ echo 123.444.888.235 | awk -F'.' -vOFS='.' '{$NF=0}1;'
123.444.888.0
ที่นี่-F'.'บอกawkให้ใช้.เป็นตัวคั่นฟิลด์อินพุตและ-vOFS='.'ใช้เป็นตัวคั่นฟิลด์เอาต์พุต จากนั้นเราก็ตั้งสนามสุดท้าย ( $NF) 0 และพิมพ์บรรทัด ( 1;เป็นawkชวเลขสำหรับ "พิมพ์บรรทัดปัจจุบัน")
$ echo 123.444.888.235 | perl -pe 's/\d+$/0/'
123.444.888.0
-pบอกพิมพ์สายการป้อนข้อมูลแต่ละหลังจากการใช้สคริปต์ที่กำหนดโดยperl สคริปต์ที่ตัวเองเป็นเพียงผู้ประกอบการเปลี่ยนตัวง่ายๆที่จะแทนที่หนึ่งหรือมากกว่าตัวเลขที่ท้ายบรรทัดที่มี -e0
$ 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 และคุณกำลังแทนที่ octet สุดท้ายของที่อยู่.0นั้นด้วยฉันคิดว่าสิ่งที่คุณพยายามทำจริงๆคือการคำนวณส่วนเครือข่ายของที่อยู่ IP โดยใช้255.255.255.0netmask
เพียงแค่แทนที่ octet ด้วย zeroes ก็โอเคถ้าความยาว netmask ของคุณหารด้วย 8 ได้ แต่นี่ไม่ใช่กรณีทั่วไป หากคุณจำเป็นต้องดำเนินการนี้กับ netmask (subnet) ใด ๆ ที่ถูกต้องคุณสามารถทำสิ่งนี้ได้:
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() แปลงรูปแบบประทศนิยมของที่อยู่ IP (หรือมาสก์) เป็นจำนวนเต็มอย่างง่ายi2d() ทำตรงกันข้าม - แปลงจำนวนเต็มอย่างง่ายเป็นทศนิยมประipmask()เพียงคำนวณค่าบิตและของที่อยู่และ netmask เพื่อให้ส่วนเครือข่ายของที่อยู่ Bash ต้องการให้ตัวถูกดำเนิน&การเป็นจำนวนเต็มการเรียกสองครั้งเพื่อipmaskแสดงวิธีคำนวณเครือข่ายจากที่อยู่ IP สำหรับมาสก์ที่แตกต่างกันสองแบบ
หมายเหตุตามที่ระบุในคำถาม123.444.888.235เป็นที่อยู่ IP ที่ไม่ถูกต้อง ฉันใช้123.44.88.235แทนตัวอย่างเหล่านี้
sedคำตอบอื่น:
sed -r 's/(.*\.).*/\10/'
มันจัดกลุ่มทุกอย่างจนถึงจุดสุดท้ายและแทนที่บรรทัดแบบเต็มด้วยเนื้อหาของกลุ่มตามด้วย 0
ฉันใช้ -r เพื่อหลีกเลี่ยงการหลีกเลี่ยงวงเล็บ