ฉันมีรูปแบบต่อไปนี้ในสตริง (ที่อยู่ 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 สำหรับมาตรฐานภาษาและขณะนี้ดำเนินการโดยเปลือกหอยทุกสิ่งที่ตีความภาษาที่รวมทั้งsh
bash
${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
สคริปต์ที่ตัวเองเป็นเพียงผู้ประกอบการเปลี่ยนตัวง่ายๆที่จะแทนที่หนึ่งหรือมากกว่าตัวเลขที่ท้ายบรรทัดที่มี -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 และคุณกำลังแทนที่ octet สุดท้ายของที่อยู่.0
นั้นด้วยฉันคิดว่าสิ่งที่คุณพยายามทำจริงๆคือการคำนวณส่วนเครือข่ายของที่อยู่ IP โดยใช้255.255.255.0
netmask
เพียงแค่แทนที่ 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 เพื่อหลีกเลี่ยงการหลีกเลี่ยงวงเล็บ