Jawaban:
2 hal:
-o
opsi, jadi hanya kecocokan yang dicetak (bukan seluruh baris)-P
pilihan, untuk menggunakan ekspresi reguler Perl, yang mencakup elemen berguna seperti Lihat di depan (?= )
dan Lihat di belakang (?<= )
, yang mencari bagian, tetapi tidak benar-benar cocok dan mencetaknya.Jika Anda hanya menginginkan bagian di dalam parensis yang cocok:
grep -oP '(?<=\/\()\w(?=\).+\/)' myfile.txt
jika file mengandung sengatan /(a)5667/
, grep akan mencetak 'a', karena:
/(
ditemukan oleh \/\(
, tetapi karena mereka berada dalam pandangan-belakang (?<= )
mereka tidak dilaporkana
dicocokkan dengan \w
dan dengan demikian dicetak (karena -o
))5667/
ditemukan b < \).+\/
, tetapi karena mereka dalam pandangan ke depan (?= )
mereka tidak dilaporkanGunakan -o
opsi di grep
.
Misalnya:
$ echo "foobarbaz" | grep -o 'b[aeiou]r'
bar
Jika Anda hanya menginginkan apa yang ada di dalam tanda kurung, Anda memerlukan sesuatu yang mendukung menangkap sub pertandingan (Kelompok Pengambilan Bernama atau Bernomor). Saya tidak berpikir grep atau egrep dapat melakukan ini, perl dan sed bisa. Misalnya, dengan perl:
Jika file yang disebut foo memiliki baris di dalamnya adalah sebagai berikut:
/adsdds /
Dan kamu juga:
perl -nle 'print $1 if /\/(\w).+\//' foo
Huruf a dikembalikan. Itu mungkin bukan yang Anda inginkan. Jika Anda memberi tahu kami apa yang ingin dicocokkan, Anda mungkin mendapatkan bantuan yang lebih baik. $ 1 adalah apa pun yang ditangkap dalam set kurung pertama. $ 2 akan menjadi set kedua dll.
Karena Anda menandai pertanyaan Anda sebagai bash selain shell , ada solusi lain selain grep :
Bash memiliki mesin ekspresi regulernya sendiri sejak versi 3.0, menggunakan =~
operator, seperti Perl.
sekarang, diberikan kode berikut:
#!/bin/bash
DATA="test <Lane>8</Lane>"
if [[ "$DATA" =~ \<Lane\>([[:digit:]]+)\<\/Lane\> ]]; then
echo $BASH_REMATCH
echo ${BASH_REMATCH[1]}
fi
bash
dan bukan hanya sh
untuk mendapatkan semua ekstensi$BASH_REMATCH
akan memberikan seluruh string sesuai dengan seluruh ekspresi reguler, jadi <Lane>8</Lane>
${BASH_REMATCH[1]}
akan memberikan bagian yang cocok dengan grup 1, dengan demikian hanya 8
>
simbol untuk tujuan yang sama sekali berbeda) sebagaimana dimuntahkan oleh perangkat lunak penyelarasan skala cepat paralel SANSparallel . Tentu saja kedua format tersebut di-interlaced tanpa ada pelarian. Jadi tidak mungkin untuk melemparkan beberapa pustaka XML standar pada ini. Dan saya menggunakan Bash regex pada titik kode ini karena saya hanya perlu mengekstrak beberapa data, dan 2 regex melakukan pekerjaan lebih baik bagi saya daripada menulis pengurai khusus untuk kekacauan ini. #LifeInBioinformatics
Dengan asumsi file tersebut berisi:
$ cat file
Text-here>xyz</more text
Dan Anda ingin karakter antara >
dan </
, Anda dapat menggunakan:
grep grep -oP '.*\K(?<=>)\w+(?=<\/)' file
sed sed -nE 's:^.*>(\w+)</.*$:\1:p' file
awk awk '{print(gensub("^.*>(\\w+)</.*$","\\1","g"))}' file
perl perl -nle 'print $1 if />(\w+)<\//' file
Semua akan mencetak string "xyz".
Jika Anda ingin menangkap digit dari baris ini:
$ cat file
Text-<here>1234</text>-ends
grep grep -oP '.*\K(?<=>)[0-9]+(?=<\/)' file
sed sed -E 's:^.*>([0-9]+)</.*$:\1:' file
awk awk '{print(gensub(".*>([0-9]+)</.*","\\1","g"))}' file
perl perl -nle 'print $1 if />([0-9]+)<\//' file
echo 'Text-<here>1234</text>-ends' | sed -E 's|.*>([[:digit:]]+)<.*|\1|'
. Dalam beberapa kasus (misalnya [0-9]
vs. [[:digit:]]
) mereka tidak membantu keterbacaan, dalam kasus lain saya pikir mereka dapat membantu (misalnya [ \t\n\r\f\v]
vs. [:space:]
).
Ini akan memenuhi apa yang Anda minta, tetapi saya tidak berpikir itu yang Anda inginkan. Saya meletakkan .*
di depan regex untuk memakan apa pun sebelum pertandingan, tapi itu adalah operasi serakah, jadi ini hanya cocok dengan \w
karakter kedua dari belakang dalam string.
Perhatikan bahwa Anda harus keluar dari parens dan +
.
sed 's/.*\(\w\).\+/\1/' myfile.txt
sed
referensi untuk melakukan itu?