Bash = ~ regex dan https://regex101.com/

12

Menggunakan https://regex101.com/ saya membuat ekspresi reguler untuk mengembalikan kemunculan pertama alamat IP dalam sebuah string.

RegExp:

(?:\d{1,3}\.)+(?:\d{1,3})

RegExp termasuk pembatas:

/(?:\d{1,3}\.)+(?:\d{1,3})/

Dengan string tes berikut:

eu-west                       140.243.64.99 

Ini mengembalikan kecocokan penuh:

140.243.64.99

Tidak peduli apa yang saya coba dengan jangkar dll, skrip bash berikut tidak akan berfungsi dengan ekspresi reguler yang dihasilkan.

temp="eu-west                       140.243.64.99            "
regexp="(?:\d{1,3}\.)+(?:\d{1,3})"
if [[ $temp =~ $regexp ]]; then
  echo "found a match"
else
  echo "No IP address returned"
fi
rjm61
sumber
3
Itu terlihat seperti ekspresi reguler Perl bagi saya. Bash tidak mendukung itu.
Kusalananda
1
The =~Operator dibahas di sini di manual mana itu ditulis pesta kegunaan "extended ekspresi reguler". Regex yang diperluas dijelaskan di regex(7)halaman manual dan diringkas secara singkat di sini .
glenn jackman

Jawaban:

15

\dadalah cara yang tidak standar untuk mengatakan "digit". Saya pikir itu berasal dari Perl, dan banyak bahasa dan utilitas lain mendukung RE yang kompatibel dengan Perl (PCRE) juga. (dan misalnya GNU grep 2.27 di Debian stretch mendukung kesamaan \wuntuk karakter kata bahkan dalam mode normal.)

Bash tidak mendukung \d, jadi Anda harus menggunakan [0-9]atau secara eksplisit [[:digit:]]. Sama untuk grup yang tidak menangkap (?:..), gunakan saja (..).

Ini harus dicetak match:

temp="eu-west                       140.243.64.99            "
regexp="([0-9]{1,3}\.)+([0-9]{1,3})"
[[ $temp =~ $regexp ]] && echo match
ilkkachu
sumber
2
Apakah GNU Anda grepmendukung \dtanpa -P?
Stéphane Chazelas
@ StéphaneChazelas, whoops, tentu saja tidak. Itu mendukung \wdan \b, yang saya pelajari dari Perl, jadi saya bingung.
ilkkachu
itu tidak benar-benar adil untuk mengatakan \datau PCRE "tidak standar". Mereka cukup standar, hanya standar yang berbeda dari ekspresi reguler asli dan ekspresi reguler lanjutan.
Daniel Farrell
1
@DanielFarrell, standar dalam hal ini adalah apa yang ditentukan POSIX , dan tidak diketahui \d. Meskipun Anda benar bahwa PCRE agak standar, atau paling tidak terdefinisi dengan baik. Masalah yang mengganggu adalah bahwa GNU grep (atau glibc) mendukung beberapa atom mirip PCRE, setidaknya \wdan \sketika menafsirkan ERE, dan dalam konteks itu mereka sangat tidak standar. Ungkapan saya mungkin sebagian berasal dari itu, dan kesalahan penilaian yang \djuga didukung oleh GNU.
ilkkachu
4

(:...)dan \dmerupakan perl atau operator ekspresi reguler PCRE (seperti di GNU grep -P).

bashhanya mendukung ekspresi reguler yang diperluas seperti pada grep -Ekecuali untuk regexps yang diteruskan secara literal sebagai [[ text =~ regexp-here ]]lawan dari hasil ekspansi yang tidak dikutip (seperti dalam [[ text =~ $var ]]atau [[ test =~ $(printf '%s\n' 'regexp-here') ]]), itu terbatas pada rangkaian fitur ekspresi reguler diperpanjang POSIX.

Jadi, bahkan pada sistem yang grep -E '\d'berfungsi (ERE GNU telah mengimpor beberapa ekstensi dari perl regexps seperti yang \smungkin dimiliki versi yang akan datang \d), Anda harus menggunakan:

regexp='\d'
[[ $text =~ $regexp ]]

di bashuntuk itu berfungsi ( [[ $text =~ \d ]]tidak akan).

Untuk shell yang mendukung PCRE, Anda mungkin ingin menggunakan zsh:

set -o rematchpcre
[[ $text =~ '(?:\d{1,3}\.)+(?:\d{1,3})' ]]

ksh93 juga mendukung penerapan ekspresi reguler seperti perl (tidak sepenuhnya kompatibel) sebagai bagian dari pencocokan pola. Di sana, Anda akan menggunakan:

regexp='~(P)(?:\d{1,3}\.)+(?:\d{1,3})'
[[ $text = $regexp ]]

(perhatikan =bukan =~. Anda akan ingin menggunakan variabel sementara karena itu sangat buggy ketika Anda tidak)

Stéphane Chazelas
sumber
1

Situs regex101.com menggunakan PCRE (lihat sudut kiri atas) sebagai default, dan tidak memiliki dukungan untuk sintaks regex "Diperpanjang". Itu adalah "Perl Regular Regular Expresions", yang datang (seperti yang masuk akal untuk diharapkan) dari Perl.

PCRE didukung oleh beberapa alat (seperti grep -P) dalam beberapa kondisi, tetapi dukungan bash regex di dalam [[…]]idiom hanya untuk perpanjangan regex (seperti grep -E).

Di Extended regex, (?…)tanda kurung non-capture tidak ada, dan \ d juga hilang. Anda perlu menggunakan yang sederhana (…)dan [0-9]:

regexp="([0-9]{1,3}\.)+([0-9]{1,3})"
Ishak
sumber