ไม่ใช่วิธีที่ง่ายที่สุดแต่คุณสามารถทำสิ่งต่อไปนี้:
$ IP=109.96.77.15
$ echo "$((${-+"(${IP//./"+256*("}))))"}&255))"
109
$ echo "$((${-+"(${IP//./"+256*("}))))"}>>8&255))"
96
$ echo "$((${-+"(${IP//./"+256*("}))))"}>>16&255))"
77
$ echo "$((${-+"(${IP//./"+256*("}))))"}>>24&255))"
15
ว่าควรจะทำงานใน ksh93 (ที่ว่า${var//pattern/replacement}ผู้ประกอบการมาจาก) bash4.3+, busybox sh, yash, mkshและzshแม้ว่าแน่นอนในzshวิธีการที่มีที่ง่ายมาก ในเวอร์ชันที่เก่ากว่าbashคุณจะต้องลบคำพูดภายใน มันใช้งานได้กับอัญประกาศภายในเหล่านั้นในเชลล์อื่น ๆ ส่วนใหญ่เช่นกัน แต่ไม่ใช่ ksh93
สมมติว่า$IPมีการแทนค่า quad-decimal ที่ถูกต้องของที่อยู่ IPv4 (แม้ว่ามันจะใช้ได้สำหรับการแทน quad-hexadecimal เช่น0x6d.0x60.0x4d.0xf(และแม้แต่เลขฐานแปดในบางเชลล์) แต่จะเอาท์พุทค่าเป็นทศนิยม) หากเนื้อหาของ$IPมาจากแหล่งที่ไม่น่าเชื่อถือนั่นจะทำให้เกิดช่องโหว่ในการฉีดคำสั่ง
โดยทั่วไปในขณะที่เรากำลังแทนที่ทุก.ใน$IPกับ+256*(เราจบลงด้วยการประเมินผล:
$(( (109+256*(96+256*(77+256*(15))))>> x &255 ))
ดังนั้นเราจึงกำลังสร้างจำนวนเต็ม 32 บิตออกจากผู้ที่ 4 ไบต์เช่นที่อยู่ IPv4 ในท้ายที่สุดคือ (แม้ว่าจะมีไบต์กลับ) ¹แล้วใช้>>, &ผู้ประกอบการที่จะดึงบิตไบต์ที่เกี่ยวข้อง
เราใช้ตัว${param+value}ดำเนินการมาตรฐาน (ที่นี่$-ซึ่งรับประกันว่าจะถูกตั้งค่าเสมอ) แทนที่จะเป็นเพียงvalueเพราะมิฉะนั้นตัวแยกวิเคราะห์ทางคณิตศาสตร์จะบ่นเกี่ยวกับวงเล็บที่ไม่ตรงกัน เปลือกที่นี่สามารถหาปิด))สำหรับการเปิด$((และจากนั้นดำเนินการขยายที่อยู่ภายในที่จะมีผลในการแสดงออกทางคณิตศาสตร์ในการประเมิน
ด้วย$(((${IP//./"+256*("}))))&255))แทนเปลือกจะรักษาที่สองและสาม)ของที่นั่นในฐานะปิด))สำหรับการ$((และรายงานข้อผิดพลาดทางไวยากรณ์
ใน ksh93 คุณสามารถทำได้:
$ echo "${IP/@(*).@(*).@(*).@(*)/\2}"
96
bash, mksh, zsh ได้คัดลอก ksh93 ของ${var/pattern/replacement}ผู้ประกอบการ แต่ไม่ว่าเป็นส่วนหนึ่งในการจัดการการจับภาพกลุ่ม zshสนับสนุนด้วยไวยากรณ์ที่แตกต่าง:
$ setopt extendedglob # for (#b)
$ echo ${IP/(#b)(*).(*).(*).(*)/$match[2]}'
96
bashไม่สนับสนุนรูปแบบบางส่วนของกลุ่มการจับภาพในการจัดการผู้ประกอบการ regexp ตรงกัน${var/pattern/replacement}แต่ไม่ได้อยู่ใน
POSIXly คุณจะใช้:
(IFS=.; set -o noglob; set -- $IP; printf '%s\n' "$2")
noglobเพื่อหลีกเลี่ยงความผิดที่ไม่ดีสำหรับค่า$IPเช่น10.*.*.*, subshell ที่จะ จำกัด $IFSขอบเขตของการเปลี่ยนแปลงเหล่านั้นกับตัวเลือกและ
IPv ที่อยู่ IPv4 เป็นจำนวนเต็ม 32 บิตและตัวอย่าง 127.0.0.1 เป็นเพียงหนึ่งในหลาย ๆ ข้อความ ที่อยู่ IPv4 ทั่วไปเดียวกันนั้นของอินเทอร์เฟซแบบวนกลับสามารถแสดงเป็น 0x7f000001 หรือ 127.1 (อาจเป็นที่ที่เหมาะสมกว่าที่นี่เพื่อบอกว่ามันเป็นที่1อยู่ในเครือข่ายคลาส A 127.0 / 8) หรือ 0177.0.1 หรือชุดอื่น ๆ ของ 1 ตัวเลข 4 ถึงแสดงเป็นฐานแปดทศนิยมหรือเลขฐานสิบหก คุณสามารถส่งต่อสิ่งเหล่านั้นทั้งหมดไปยังpingและคุณจะเห็นว่าพวกเขาทั้งหมดจะ ping localhost
หากคุณไม่คำนึงถึงผลข้างเคียงของการตั้งค่าตัวแปรชั่วคราวแบบสุ่ม (ที่นี่$n) ในbashหรือksh93หรือzsh -o octalzeroesหรือlksh -o posixคุณสามารถแปลงการแทนค่าทั้งหมดเหล่านั้นกลับไปเป็นจำนวนเต็ม 32 บิตด้วย:
$((n=32,(${IP//./"<<(n-=8))+("})))
จากนั้นแยกส่วนประกอบทั้งหมดด้วย>>/ &ชุดเหมือนด้านบน
$ IP=0x7f000001
$ echo "$((n=32,(${IP//./"<<(n-=8))+("})))"
2130706433
$ IP=127.1
$ echo "$((n=32,(${IP//./"<<(n-=8))+("})))"
2130706433
$ echo "$((n=32,((${IP//./"<<(n-=8))+("}))>>24&255))"
127
$ perl -MSocket -le 'print unpack("L>", inet_aton("127.0.0.1"))'
2130706433
mkshใช้จำนวนเต็ม 32 บิตที่มีลายเซ็นสำหรับนิพจน์ทางคณิตศาสตร์คุณสามารถใช้ที่$((# n=32,...))นั่นเพื่อบังคับให้ใช้ตัวเลข 32 บิตที่ไม่ได้ลงชื่อ (และposixตัวเลือกสำหรับให้รับรู้ค่าคงที่แปด)
IFSที่readนั่น:IFS=. read -a ArrIP<<<"$IP"