Soru Bütün hatta gerek yok, sadece normal ifadeden eşleşme


Eşleşmeyi normal ifadeden almam gerek:

$ cat myfile.txt | SOMETHING_HERE "/(\w).+/"

Çıkış, sadece parantez içinde eşleştirilene göre olmalıdır.

Kullanabileceğimi düşünme grep çünkü tüm çizgiyle eşleşiyor.

Lütfen bunu nasıl yapacağımı bana bildirin.


7
2017-08-06 16:34


Menşei




Cevaplar:


2 şey:

  • @Rory tarafından belirtildiği gibi, -o seçenek, bu yüzden sadece maç yazdırılır (tüm satır yerine)
  • Ek olarak, -P seçeneği gibi yararlı öğeleri içeren Perl düzenli ifadeleri kullanmak için İleriye bak  (?= ) ve Arkana bak  (?<= )Bunlar parçalar arar, ancak aslında onları eşleştirmez ve yazdırmaz.

Parensis'in içindeki parçanın sadece eşleşmesini istiyorsanız:

grep -oP '(?<=\/\()\w(?=\).+\/)' myfile.txt

eğer dosya sokmayı içerirse /(a)5667/grep 'a' yazdı, çünkü:

  • /( tarafından bulunur \/\(ama onlar bir arkana bak  (?<= ) rapor edilmiyor
  • a tarafından eşleştirildi \w ve dolayısıyla yazdırılır -o )
  • )5667/ bulunur b < \).+\/ama onlar bir İleriye  (?= ) rapor edilmiyor

6
2018-01-20 13:21





Kullan -o seçeneği grep.

Örneğin:

$ echo "foobarbaz" | grep -o 'b[aeiou]r'
bar

14
2017-08-06 16:36



İyi keder ... Kaç kere güreşdiğim hakkında bir fikrin var mı? sed Bunu yapmak için backreferences? - Insyte
O grep / egrep seçeneğinin seçilmesi, yalnızca istediği gibi () içinde değil, yalnızca tüm normal ifadeyle eşleşen öğeyi döndürür. - Kyle Brandt♦
Ancak, bu zaten bilmek için çok iyi bir şey :-) - Kyle Brandt♦
@KyleBrandt: Sadece bir parçayla eşleşmek için (örneğin, pariteler) geri kalanını ileriye dönük olarak işaretlemek veya arkasına bakmak mümkündür: (? <=) Ve (? =) - DrYak


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. Bence grep veya egrep bunu yapabilir, perl ve sed can. Örneğin, perl ile:

Foo adında bir dosyada aşağıdaki gibi bir satır varsa:

/adsdds      /

Ve sende yap:

perl -nle 'print $1 if /\/(\w).+\//' foo

Mektup a döndü. İstediğin şey bu olmayabilir. Ne eşleştirmeye çalıştığınızı söylerseniz daha iyi yardım alabilirsiniz. $ 1, ilk parantez kümesinde yakalanan her şeydir. 2 $ ikinci set vb.


4
2017-08-06 17:38



Sadece parantez içinde olanı eşleştirmeye çalışıyordum. Bir perl'e geçmek gibi görünüyor ya da bir php betiği cevabı olabilir. - Alex L


Çünkü sorunuzu şu şekilde etiketlediniz: darbe ek olarak kabukyanında başka bir çözüm var grep :

Bash, 3.0 sürümünden beri kendi düzenli ifade motoruna sahiptir. =~ Operatör, tıpkı Perl gibi.

şimdi, aşağıdaki kod göz önüne alındığında:

#!/bin/bash
DATA="test <Lane>8</Lane>"

if [[ "$DATA" =~ \<Lane\>([[:digit:]]+)\<\/Lane\> ]]; then
        echo $BASH_REMATCH
        echo ${BASH_REMATCH[1]}
fi
  • Bunu çağırmak zorunda olduğunuzu unutmayın. bashve sadece değil sh tüm uzantıları almak için
  • $BASH_REMATCH tüm dizgiyi tüm normal ifadeyle eşleştirecek şekilde <Lane>8</Lane>
  • ${BASH_REMATCH[1]} 1. grup tarafından eşleştirilen kısmı verecek, sadece 8

3
2018-01-20 13:47



Sevgili @DrYak, umarım burada regex ile XML ayrıştırmadığınızı umuyorum .. :) - joonas.fi
Daha da kötüsü. XML ve FASTA verilerinin korkunç bir karışımını ayrıştırıyorum. > Tamamen farklı amaçlar için sembol) SANSparallel hızlı largescale hizalama yazılımı. Tabii ki, her iki format da kaçmaksızın taramalı. Bu yüzden bazı standart XML kütüphaneleri atmak imkansız. Ve kodun bu noktasında Bash regex kullanıyorum çünkü sadece birkaç veriyi çıkartmam gerekiyor, ve 2 regex işi bu karmaşa için özel bir ayrıştırıcı yazmaktan çok daha iyi yapıyor. #LifeInBioinformatics - DrYak
Başka bir deyişle: 1 tek sayının çıkarılmasının, tüm XML tangolarını dans etmekten daha fazla bir regex rathan ile daha basit bir nokta olduğu bir nokta var. - DrYak
Hah, yakaladın! :) - joonas.fi


    sed -n "s/^.*\(captureThis\).*$/\1/p"

-n      don't print lines
s       substitute
^.*     matches anything before the captureThis 
\( \)   capture everything between and assign it to \1 
.*$     matches anything after the captureThis 
\1      replace everything with captureThis 
p       print it

2
2018-04-22 15:58





Bu, istediğini yerine getirecek, ama gerçekten istediğin şey olduğunu düşünmüyorum. Koydum .* maçtan önce bir şey yemeye regex önünde, ama bu açgözlü bir işlemdir, bu yüzden sadece sondan bir önceki \w dizede karakter.

Parens'ten ve +.

sed 's/.*\(\w\).\+/\1/' myfile.txt

0
2017-08-06 18:02





Dosyanın içerdiğini varsayarsak:

$ cat file
Text-here>xyz</more text

Ve sen arasında karakter (ler) istiyorsun > ve </ aşağıdakilerden birini kullanabilirsiniz:

  grep -oP '.*\K(?<=>)\w+(?=<\/)' file
  sed -nE 's:^.*>(\w+)</.*$:\1:p' file
  awk '{print(gensub("^.*>(\\w+)</.*$","\\1","g"))}' file
  perl -nle 'print $1 if />(\w+)<\//' file

Hepsi bir "xyz" dizgisi yazdıracaktır.

Bu satırın rakamlarını yakalamak istiyorsanız:

$ cat file
Text-<here>1234</text>-ends

  grep -oP '.*\K(?<=>)[0-9]+(?=<\/)' file
  sed -E 's:^.*>([0-9]+)</.*$:\1:' file
  awk '{print(gensub(".*>([0-9]+)</.*","\\1","g"))}' file
  perl -nle 'print $1 if />([0-9]+)<\//' file


0
2017-07-22 08:01