Keyinchalik ma'lum bir mag'lubiyatni qidirganda, ochko'z o'yinni qanday engish kerak?

echo "A number is about to show up 1 and now I want to parse 365 guys and some extra junk"  | sed -E 's/.*([0-9]+) guys.*/\1/g'

Yuqoridagi buyruqlar faqat 5 chiqdi. Aslida men "bolalarni" raqamlarini raqamlar bo'lishi mumkin bo'lgan tasodifiy jumla bilan ajralib chiqmoqchiman (yoki "kod" echimini "365 bolalar" deb atashni istayman). bolalar. . 36 bilan mos keladi va uni \ 1 ko'rinishida bo'lishiga to'sqinlik qilmoqda. Men xohlagan narsani bajarish uchun qanday qilib sed buyrug'ini (yoki boshqa regex/perl/awk) yozishim mumkin?

2

7 javoblar

Perldagi "odatiy" kodifikatorni *? dan foydalaning:

perl -pe 's/.*?([0-9]+) guys.*/$1/'
5
qo'shib qo'ydi
Bundan tashqari, perl-lne/m/(\ d +) guys/va $ 1 bosib chiqarishni taklif qilaman
qo'shib qo'ydi muallif Sobrique, manba
@Borodin: U erda siz uni almashtirishni xohlaysiz. Albatta muammoni hal qilishning boshqa yo'llari bor.
qo'shib qo'ydi muallif choroba, manba
Hech bo'lmasa, . * uchun hech qanday sabab yo'q
qo'shib qo'ydi muallif Borodin, manba
Axir, men bu o'zgarish ekanini bilmay qoldim
qo'shib qo'ydi muallif Borodin, manba

GNU grep bilan bilan:

$ grep -Po '\b[0-9]+(?= guys\b)' <<<"365 guys or 366 guys, but not foo12 guys."
365
366
  • -P actives support for PCREs, which enables advanced regex features.
  • -o specifies that only the matching parts of input lines should be printed.
  • \b matches only on a word boundary, including at the start of a line;
    this prevents matching numbers that aren't stand-alone numbers but part of other words, such as in foo365 guys, and words that start with guys, such as guysanddolls.
  • (?= guys) is a look-ahead assertion that matches the enclosed subexpression without including it in the matched string returned.

Ko'rsatilganidek, bu ma'lum bir satrda bir nechta </​​em> naqshlari bilan mos kelishi mumkin va har bir raqam o'z chiqish liniyasida chop etiladi. Agar istamasangiz, grep ishlatilmaydi, chunki -o always inverse barcha satrlarni mos keladigan narsalarni qaytaradi; echim uchun quyidagi perl buyrug'ini ko'ring.


Sobrique ning choroba javobidan ilhomlangan perl munosib Yuqoridagi grep buyrug'i:

$ perl -lne 'print for m/\b(\d+) guys\b/g' <<<"365 guys or 366 guys, but not foo12 guys."
365
366

Faqatgina 1 qatoriga mos keladigan kodni g qo'ying.

2
qo'shib qo'ydi

Raqamingiz bo'sh bo'lganidan oldin uni regexning bir qismiga aylantirasiz:

echo "A number is about to show up 1 and now I want to parse 365 guys and some extra junk"  | sed -E 's/.* ([0-9]+) guys.*/\1/g'

# => 365
1
qo'shib qo'ydi
ajoyib taklif, ammo mening gapim doimo oldindan joy bo'lmasligi mumkin. "365 ta bolalar va bir nechta arzimas" echo ham joriy kirishdir. Men savolni yanada mustahkam qiladi. Sizga raxmat!
qo'shib qo'ydi muallif Andrew Cassidy, manba

Bashda:

$ s="A number is about to show up 1 and now I want to parse 365 guys and some extra junk"
$ [[ $s =~ ([0-9]+)\ +guys.*$ ]] && echo ${BASH_REMATCH[1]}
365

Yoki, awk bilan:

$ echo "$s" | awk '/guys/{for (i=1;i<=NF;i++) if ($i=="guys" && $(i-1)+0==$(i-1)) print $(i-1)}'
365
1
qo'shib qo'ydi

standart sed regex bilan siz mag'lubiyatga teskari va mos keladigan bo'lsa, ochko'z o'yindan foydalanishingiz mumkin

echo ... | rev | sed -E 's/.*syug ([0-9]+).*/\1/g' | rev

Shubhasiz, bu hack, ammo umidsiz vaqtlar ...

0
qo'shib qo'ydi

Bu siz uchun ishlashi mumkin (GNU sed)

 sed -r 's/.*\b([0-9]+) guys.*/\1/' file

yoki ehtimol:

 sed -r 's/.*\<([0-9]+) guys.*/\1/' file

Chiziqning son qismini so'z chegarasiga moslashtiring.

0
qo'shib qo'ydi

@Andrew Cassidy: @try:

   echo "A number is about to show up 1 and now I want to parse 365 guys and some extra junk"  |
awk '/guys/{print VAL;exit} {VAL=$0}' RS=" "
0
qo'shib qo'ydi