Memaksa Bash untuk menggunakan Mesin Perl RegEx


11

Seperti yang mungkin sudah Anda ketahui, banyak fitur yang didukung oleh mesin RegEx modern (referensi balik, pernyataan lookaround, dll.) Tidak didukung oleh mesin Bash RegEx. Berikut ini adalah skrip Bash sederhana yang baru saja saya buat untuk mencoba menjelaskan apa tujuan akhir saya:

#!/bin/bash

# Make sure exactly two arguments are passed.
if [ $# -lt 2 ]
then
    echo "Usage: match [string] [pattern]"
    return
fi

variable=${1}
pattern=${2}

if [[ ${variable} =~ ${pattern} ]]
then
    echo "true"
else
    echo "false"
fi

Jadi misalnya, sesuatu seperti perintah berikut ini akan kembali salah:

. match.sh "catfish" "(?=catfish)fish"

sedangkan ekspresi yang sama persis akan menemukan kecocokan saat digunakan dalam Perl atau penguji regex JavaScript.

Referensi balik (mis. (Expr1) (expr2) [] \ 1 \ 2) tidak akan cocok juga.

Saya hanya sampai pada kesimpulan bahwa masalah saya hanya akan diselesaikan ketika memaksa bash untuk menggunakan mesin RegEx yang kompatibel dengan Perl. Apakah ini bisa dilakukan? Jika demikian, bagaimana saya menjalankan prosedur?


5
Mengapa Anda tidak menggunakan perl saja alih-alih bash untuk skrip? Dan mengapa pertanyaan ini ditandai dengan javascript?
Marco

Karena menggunakan Bash adalah suatu keharusan dalam situasi saya. Dan saya tidak sengaja menandai JavaScript. Saya menghapusnya :)
Fadi Hanna AL-Kass

2
Mengapa Anda tidak menggunakan grepdengan -Patau menggunakan sed?
cuonglm

2
Tetapi Anda tidak pernah menjelaskan situasi / masalah yang membuat Anda sampai pada kesimpulan bahwa Anda harus membuat shell melakukan sesuatu yang tidak bisa dilakukan. Ada cara yang lebih baik.
llua

Saya menemukan bahwa backreferences melakukan pekerjaan di bash 4.3.x (Ubuntu 14.04), tetapi tidak di bash 3.2x (OS X). Ini adalah perintah pengujian saya:re="([a-z])[0-9]\1"; [[ a1a =~ $re ]] && echo ${BASH_REMATCH[0]}
Digital Trauma

Jawaban:


14

Bash tidak mendukung metode bagi Anda untuk melakukan ini saat ini. Anda memiliki opsi berikut:

  1. Gunakan Perl
  2. Menggunakan grep [-P|--perl-regexp]
  3. Gunakan fungsi Bash untuk mengkodekannya

Saya pikir saya akan pergi dengan # 2 dan mencoba dan gunakan grepuntuk mendapatkan apa yang saya inginkan secara fungsional. Untuk referensi balik Anda dapat melakukan hal berikut dengan grep:

$ echo 'BEGIN `helloworld` END' | grep -oP '(?<=BEGIN `).*(?=` END)'
helloworld

-o, --only-matching       show only the part of a line matching PATTERN
-P, --perl-regexp         PATTERN is a Perl regular expression

(?=pattern)
    is a positive look-ahead assertion
(?!pattern)
    is a negative look-ahead assertion
(?<=pattern)
    is a positive look-behind assertion
(?<!pattern)
    is a negative look-behind assertion 

Referensi


Jujur saya tidak tahu grep punya [-P|--perl-regexp]token. Terima kasih banyak :-)
Fadi Hanna AL-Kass

@ FadiHannaAL-Kass - sama-sama Terima kasih untuk pertanyaannya.
slm

2
Untuk anak cucu, hanya GNU grep yang menyertakan -Popsi, dan itu tidak universal. Grep FreeBSD didasarkan pada GNU, tetapi dokumentasi menyatakan "Opsi ini tidak didukung dalam FreeBSD". Di OSX, grep juga didasarkan pada GNU, tetapi -Popsi bahkan tidak disebutkan di halaman manual. Dan pada sistem unix lain yang grep bukan GNU, Anda tidak mungkin melihat -Pdi mana pun. Jika ada kemungkinan jauh Anda bahwa portabilitas mungkin berguna bagi Anda di masa depan, saya sarankan menghindari opsi spesifik OS seperti ini.
ghoti

pcregrepjuga merupakan opsi, jika tersedia.
Wildcard

Perlu dicatat bahwa zsh melakukan persis apa yang diminta OP, selama REMATCH_PCREopsi tersebut ditetapkan.
Tim Peoples

0

Orang bisa menggunakan pcregrep. Muncul dengan paket pcredi CentOS dan pcregrepdi Ubuntu.

grep -P dapat memiliki masalah ini tergantung pada OS / versi:

-P, --perl-regexp
              Interpret PATTERN as a Perl regular expression.  This is highly experimental and grep -P may warn of unimplemented features.
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.