sed: yalnızca eşleşen grubu yazdır


133

Son iki sayıyı (bir int, bir kayan nokta; ardından isteğe bağlı boşluk) alıp yalnızca yazdırmak istiyorum.

Misal:

foo bar <foo> bla 1 2 3.4

Yazdırmalı:

2 3.4

Şimdiye kadar aşağıdakilere sahibim:

sed -n  's/\([0-9][0-9]*[\ \t][0-9.]*[\ \t]*$\)/replacement/p' 

bana verecek

foo bar <foo> bla 1 replacement

Ancak, bunu 1. grupla değiştirmeye çalışırsam, tüm satır yazdırılır.

sed -n  's/\([0-9][0-9]*[\ \t][0-9.]*[\ \t]*$\)/\1/p' 

Satırın yalnızca gruptaki normal ifade ile eşleşen bölümünü nasıl yazdırabilirim?

Yanıtlar:


138

Tüm satırı eşleştirin, bu nedenle .*normal ifadenizin başına bir ekleyin . Bu, tüm satırın grubun içeriğiyle değiştirilmesine neden olur

echo "foo bar <foo> bla 1 2 3.4" |
 sed -n  's/.*\([0-9][0-9]*[\ \t][0-9.]*[ \t]*$\)/\1/p'
2 3.4

38
-rVeya "--regexp-extended" seçeneğini eklemek zorunda kaldım, aksi takdirde invalid reference \1 on s "command's RHS" hatasını alıyordum .
— Daniel Sokolowski

15
@DanielSokolowski Sana kullanırsanız o hatayı alıyorum düşünüyorum (ve )yerine \(ve \).
— Daniel Darabos

3
.*Ayıklamak istediğiniz dize her zaman satırın sonunda değilse, normal ifadenin sonuna eklemeyi unutmayın .
— Teemu Leisti

3
Bu benim için işe yaramayacak çünkü .*açgözlü ve açgözlü değil.*?
— sondra.kinsey

@DanielDarabos Sadece bunu belirtin (ve )ubuntu 16.04'te hata yaratmayacaktır. Bu yüzden bu yorumun modası geçmiş olduğunu düşünüyorum.
— Li haonan

72

grep , ayıklamak için doğru araçtır.

örneğinizi ve normal ifadenizi kullanarak:

kent$  echo 'foo bar <foo> bla 1 2 3.4'|grep -o '[0-9][0-9]*[\ \t][0-9.]*[\ \t]*$'
2 3.4

12
tüm grup için harika, ancak bireysel gruplar için sed gerekli
— jozxyqk

grep -o msysgit çalıştıran sistemlerde bağlantı sağlamaz, ancak sed yapar.
— cchamberlain

Bunu grep ile çözmek için ileriye bakma ve arkaya bakma kullanan bir yanıt için @jozxyqk ile bağlantılı soruya bakın.
— Joachim Breitner

Yönlendirmeli grep -oaramalar içeren bir modelden bir grubu çıkarabilirsiniz . stackoverflow.com/a/58314379/117471
— Bruno Bronosky

12

Ve başka bir seçenek için, awk ile giderdim!

echo "foo bar <foo> bla 1 2 3.4" | awk '{ print $(NF-1), $NF; }'

Bu, girişi (burada STDIN kullanıyorum, ancak girişiniz kolayca bir dosya olabilir) boşluklara böler ve ardından son-bir-bir alanı ve sonra son alanı yazdırır. $NFDeğişkenler alan sayısı boşluk üzerinde patlayan sonra bulundu tutun.

Bunun yararı, son iki alandan önce gelen şeyin değişip değişmediğinin önemli olmamasıdır, sadece son ikisini istediğiniz sürece çalışmaya devam edecektir.


3

Kes komutu tam bu durum için tasarlanmıştır. Herhangi bir sınırlayıcı üzerinde "keser" ve sonra hangi parçaların çıktılacağını belirleyebilirsiniz.

Örneğin: echo "foo bar <foo> bla 1 2 3.4" | cut -d " " -f 6-7

Şu çıktıyla sonuçlanacak: 2 3.4

-d sınırlayıcıyı ayarlar

-f, çıktılanacak 'alanlar' aralığını seçer, bu durumda, orijinal dizginin 6'dan 7'ye kadar olan parçalarıdır. Aralığı gibi bir liste olarak da belirtebilirsiniz 6,7.


Yalnızca belirli sütunları yazdırmak içinawk '{ print $2" "$6 }'
— nurettin

@nurettin Bence yorumunuz garip cevaplardan biri için yapılmış olabilir.
— carlin.scott

Bu sayfayı ziyaret ettiğimde kesmeyi denedim ve sınırlamalarını fark ettim ve bu yazının kalitesini artırmak için yorum yapmak yerine awk'de daha genelleştirilmiş bir sürüm yazmaya karar verdim.
— nurettin

1
Evet, bence bu, awk ile ilgili farklı bir cevaba ait. Yazdıklarınızı yapmak için kesme komutu:cut -d " " -f 2,6
— carlin.scott

Ah, bunu bilmiyordum, sadece aralık verebileceğini düşünmüştüm. Bunun için teşekkürler.
— nurettin

2

@Kent'in bunun için çok uygun olduğuna katılıyorum grep -o. Bir desen içindeki bir grubu çıkarmanız gerekirse, bunu 2. bir grep ile yapabilirsiniz.

# To extract \1 from /xx([0-9]+)yy/
$ echo "aa678bb xx123yy xx4yy aa42 aa9bb" | grep -Eo 'xx[0-9]+yy' | grep -Eo '[0-9]+'
123
4

# To extract \1 from /a([0-9]+)b/
$ echo "aa678bb xx123yy xx4yy aa42 aa9bb" | grep -Eo 'a[0-9]+b' | grep -Eo '[0-9]+'
678
9
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.