Yanıtlar:
2 şey:
-o
seçeneğe ihtiyacınız vardır , bu nedenle sadece eşleşme yazdırılır (tüm satır yerine)-P
gibi yararlı öğeleri içeren Perl düzenli ifadelerini kullanma seçeneğinden de yararlanabilirsiniz, bunlar parçaları arar, ancak aslında eşleşmez ve yazdırmaz. (?= )
(?<= )
Yalnızca parensisin içindeki kısmın eşleşmesini istiyorsanız:
grep -oP '(?<=\/\()\w(?=\).+\/)' myfile.txt
dosyada sokma varsa /(a)5667/
, grep 'a' yazacaktır, çünkü:
/(
tarafından bulunur \/\(
, ancak arkalarında (?<= )
oldukları için rapor edilmezlera
ile eşleştirilir \w
ve böylece yazdırılır (nedeniyle -o
))5667/
b <bulunur \).+\/
, ancak ileriye yönelik (?= )
olduklarından rapor edilmezler.İçindeki -o
seçeneği kullanın grep
.
Örneğin:
$ echo "foobarbaz" | grep -o 'b[aeiou]r'
bar
Yalnızca parantez içinde ne istiyorsanız, alt eşleşmeleri (Adlandırılmış veya Numaralı Yakalama Grupları) yakalamayı destekleyen bir şeye ihtiyacınız vardır. Ben grep veya egrep bunu yapabilir, perl ve sed yapabilirsiniz sanmıyorum. Örneğin, perl ile:
Foo adlı bir dosyada aşağıdaki gibi bir çizgi varsa:
/adsdds /
Ve sende yap:
perl -nle 'print $1 if /\/(\w).+\//' foo
A harfi döndürülür. Gerçi istediğin bu olmayabilir. Neyi eşleştirmeye çalıştığınızı söylerseniz, daha iyi yardım alabilirsiniz. İlk parantez kümesinde yakalanan $ 1. 2 $ ikinci set vb. Olur.
Siz sorunuzu etiketlenmiş Çünkü bash ek olarak kabuk , yanında başka çözüm yoktur grep :
Bash, =~
Perl gibi , operatörü kullanarak sürüm 3.0'dan beri kendi normal ifade motoruna sahiptir .
Şimdi, aşağıdaki kod verildiğinde:
#!/bin/bash
DATA="test <Lane>8</Lane>"
if [[ "$DATA" =~ \<Lane\>([[:digit:]]+)\<\/Lane\> ]]; then
echo $BASH_REMATCH
echo ${BASH_REMATCH[1]}
fi
bash
değil, onu çağırmanız gerektiğini unutmayınsh
$BASH_REMATCH
tüm dizeyi tüm normal ifadeyle eşleştirildiği şekilde verecektir. <Lane>8</Lane>
${BASH_REMATCH[1]}
1. grup tarafından eşleşen kısmı verecektir, bu yüzden sadece 8
>
tarafından spewed gibi korkunç bir XML ve FASTA veri karışımı (her ikisi de tamamen farklı amaçlar için kullanın ) ayrıştırıyorum . Tabii ki her iki format da kaçmadan aralıklı olarak yazılmıştır. Bu nedenle, buna standart bir XML kitaplığı atmak imkansız. Ve kodun bu noktasında Bash regex kullanıyorum çünkü sadece birkaç veri ayıklamak gerekiyor ve 2 regex bu karmaşa için özel bir ayrıştırıcı yazmaktan çok benim için işi daha iyi yapıyor. Bioinformatik
Dosyanın içerdiği varsayılarak:
$ cat file
Text-here>xyz</more text
Ve karakter (ler) arasında olmasını istediğiniz >
ve </
, sen birini kullanabilirsiniz:
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
Tümü "xyz" dizesini basacaktır.
Bu satırın rakamlarını yakalamak istiyorsanız:
$ 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|'
. Bazı durumlarda (örn. [0-9]
Vs. [[:digit:]]
) okunabilirliğe yardımcı olmazlar, diğerlerinde bence (ör. [ \t\n\r\f\v]
Vs. [:space:]
).
\d
çalışmayan karakter grubu hakkındaki yorumundan bahsediyor ve dikkatlerini POSIX karakter sınıflarına çekiyordum.
Bu, talep ettiğiniz şeyi başaracak, ama gerçekten istediğiniz şey olduğunu sanmıyorum. .*
Maçtan önce herhangi bir şey yemek için normal ifadenin önüne koydum , ama bu açgözlü bir işlem, bu yüzden sadece \w
dizedeki sondan bir önceki karakterle eşleşiyor .
Parens ve +
.
sed 's/.*\(\w\).\+/\1/' myfile.txt
sed
yapmak için geri başvurularla kaç kez güreştiğim hakkında bir fikrin var mı?