แทนที่สตริงหลังจากจุดสุดท้ายในทุบตี


12

ฉันมีรูปแบบต่อไปนี้ในสตริง (ที่อยู่ IP):

123.444.888.235

ฉันต้องการแทนที่หมายเลขสุดท้ายหลังจากจุดด้วย0ดังนั้นมันจะกลายเป็น:

123.444.888.0

ฉันจะทำในbashภาษาสคริปต์ภาษาอื่นได้อย่างไร


1
สตริงเหล่านั้นอยู่ที่ไหน ในตัวแปรทุบตี? ในไฟล์ข้อความหนึ่งรายการต่อบรรทัด?
Stéphane Chazelas

มันอยู่ในตัวแปร ฉันขอโทษที่ลืมพูดถึงมัน
Ari

3
หากเป็นที่อยู่ IP ดังนั้น 444 และ 888 จึงเป็นค่าออคเต็ตที่ไม่ถูกต้อง
Digital Trauma

คำตอบ:


24

ใน 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%.*}
เสียง

@ tjt263 ที่ประเภทบรรทัดคำสั่งman bashและกด Enter จากนั้นพิมพ์/suffix patternและกด Enter :)
สัญลักษณ์แทน

เพิ่มคำพูดตามโพสต์ของคุณ : 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), ตัดแบ่งด้วยศูนย์ตัวอักษร


5

สองสามวิธี (สิ่งเหล่านี้ถือว่าคุณต้องการเปลี่ยนตัวเลขชุดสุดท้ายในสตริง):

$ 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

5

กรณีทั่วไปสำหรับการใช้ netmask กับที่อยู่ IP:

ระบุว่าการป้อนข้อมูลของคุณเป็นที่อยู่ 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แทนตัวอย่างเหล่านี้


0

sedคำตอบอื่น:

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

มันจัดกลุ่มทุกอย่างจนถึงจุดสุดท้ายและแทนที่บรรทัดแบบเต็มด้วยเนื้อหาของกลุ่มตามด้วย 0
ฉันใช้ -r เพื่อหลีกเลี่ยงการหลีกเลี่ยงวงเล็บ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.