Không phải dễ nhất , nhưng bạn có thể làm một cái gì đó như:
$ 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
Điều đó sẽ làm việc trong ksh93 (nơi mà ${var//pattern/replacement}
nhà điều hành xuất phát từ), bash
4.3 trở lên, busybox sh
, yash
, mksh
và zsh
, mặc dù tất nhiên trong zsh
, có những cách tiếp cận đơn giản hơn nhiều . Trong các phiên bản cũ hơn bash
, bạn cần xóa các trích dẫn bên trong. Nó hoạt động với những trích dẫn bên trong được loại bỏ trong hầu hết các shell khác, nhưng không phải là ksh93.
Giả định đó $IP
chứa một biểu diễn thập phân bốn thập phân hợp lệ của một địa chỉ IPv4 (mặc dù điều đó cũng sẽ hoạt động cho các biểu diễn thập lục phân như 0x6d.0x60.0x4d.0xf
(và thậm chí là bát phân trong một số vỏ) nhưng sẽ xuất ra các giá trị theo số thập phân). Nếu nội dung $IP
đến từ một nguồn không đáng tin cậy, điều đó sẽ gây ra lỗ hổng tiêm lệnh.
Về cơ bản, như chúng ta đang thay thế mỗi .
năm $IP
với +256*(
, chúng tôi kết thúc đánh giá:
$(( (109+256*(96+256*(77+256*(15))))>> x &255 ))
Vì vậy, chúng tôi đang xây dựng một số nguyên 32 bit ra khỏi những 4 byte như một địa chỉ IPv4 cuối cùng là (mặc dù với các byte đảo ngược) ¹ và sau đó sử dụng >>
, &
khai thác Bitwise để trích xuất các byte có liên quan.
Chúng tôi sử dụng ${param+value}
toán tử tiêu chuẩn (ở đây $-
được đảm bảo luôn được đặt) thay vì chỉ value
vì nếu không, trình phân tích cú pháp số học sẽ phàn nàn về dấu ngoặc đơn không khớp. Shell ở đây có thể tìm thấy sự đóng cửa ))
cho việc mở $((
, và sau đó thực hiện các mở rộng bên trong sẽ dẫn đến biểu thức số học để đánh giá.
Với $(((${IP//./"+256*("}))))&255))
thay vào đó, vỏ sẽ đối xử thứ hai và thứ ba )
ở đó như đóng cửa ))
cho $((
và báo cáo một lỗi cú pháp.
Trong ksh93, bạn cũng có thể làm:
$ echo "${IP/@(*).@(*).@(*).@(*)/\2}"
96
bash
, mksh
, zsh
Đã sao chép ksh93 của ${var/pattern/replacement}
nhà điều hành nhưng không phải là chụp nhóm xử lý một phần. zsh
hỗ trợ nó với một cú pháp khác nhau:
$ setopt extendedglob # for (#b)
$ echo ${IP/(#b)(*).(*).(*).(*)/$match[2]}'
96
bash
không hỗ trợ một số hình thức xử lý nhóm chụp trong toán tử so khớp regrec của nó , nhưng không hỗ trợ${var/pattern/replacement}
.
POSIXly, bạn sẽ sử dụng:
(IFS=.; set -o noglob; set -- $IP; printf '%s\n' "$2")
Để noglob
tránh những bất ngờ xấu cho các giá trị $IP
like 10.*.*.*
, subshell để giới hạn phạm vi của những thay đổi đó đối với các tùy chọn và $IFS
.
Địa chỉ IPv4 chỉ là số nguyên 32 bit và ví dụ 127.0.0.1 chỉ là một trong nhiều cách trình bày văn bản (mặc dù phổ biến nhất). Địa chỉ IPv4 điển hình tương tự của giao diện loopback cũng có thể được biểu diễn dưới dạng 0x7f000001 hoặc 127.1 (có thể là 1
địa chỉ thích hợp hơn ở đây để nói đó là địa chỉ trên mạng A lớp 127.0 / 8) hoặc 0177.0.1 hoặc các kết hợp khác của 1 đến 4 số được biểu thị dưới dạng bát phân, thập phân hoặc thập lục phân. Bạn có thể chuyển tất cả những thứ đó ping
chẳng hạn và bạn sẽ thấy tất cả chúng sẽ ping localhost.
Nếu bạn không nhớ các tác dụng phụ của thiết lập một biến tạm thời tùy ý (ở đây $n
), trong bash
hay ksh93
hay zsh -o octalzeroes
hay lksh -o posix
, bạn chỉ có thể chuyển đổi tất cả những cơ quan đại diện trở lại một số nguyên 32 bit với:
$((n=32,(${IP//./"<<(n-=8))+("})))
Và sau đó trích xuất tất cả các thành phần với >>
/ &
kết hợp như trên.
$ 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
sử dụng các số nguyên 32 bit đã ký cho các biểu thức số học của nó, bạn có thể sử dụng $((# n=32,...))
ở đó để buộc sử dụng các số 32 bit không dấu (và posix
tùy chọn cho nó để nhận ra các hằng số bát phân).
IFS
choread
có:IFS=. read -a ArrIP<<<"$IP"