Acties:
  • 0 Henk 'm!

  • Tony L
  • Registratie: September 2005
  • Laatst online: 07-11-2015
Ik kom er achter dat grep eigenlijk wel een hele krachtige tool is maar ik krijg bepaalde dingen nog niet helemaal werkend. Met de onderstaande command-line krijg een lading bestanden terug die precies doet aan de opgegeven filter.

find ./ -name '*.txt' | xargs grep -l -i -E '(zoeken op )(tekst|text)'

De bestanden in kwestie heten alsvolgt:
1000_naam.txt
1003_naam.txt
99911_naam.txt
etc.

Ik wil eigenlijk een lijst terug krijgen met alleen de nummers in de bestandsnaam:
1000
1003
99911

Ik had het idee om er weer een pipe (|) achter te zetten:
find ./ -name '*.txt' | xargs grep -l -i -E '(zoeken op )(tekst|text)' | xargs grep -l -i -o -E '[0-9]*'

Echter geeft dit niet het gewenste resultaat.
Heeft iemand enig idee wat ik moet doen om dit mogelijk te maken?

PSN: Norfirin


Acties:
  • 0 Henk 'm!

  • VyperX
  • Registratie: Juni 2001
  • Laatst online: 14-08 13:04
Ik weet niet zeker of grep hier de goede tool voor is. Ik zou eerder naar sed grijpen.

Grep is meer bedoeld voor het zoeken naar het voorkomen van stukken tekst. Sed doet ook echt matching/filtering op de tekst.

My Dwarf Fortress ASCII Reward: ~~@~~####,.".D",.B""


Acties:
  • 0 Henk 'm!

  • u_nix_we_all
  • Registratie: Augustus 2002
  • Niet online
Sed kan, awk ook. Maar voor een beginner (nofi) zijn dit soms lastige tooltjes.
Heel quick-and-dirty kun je het ook met cut doen, en dan die underscore als delimiter:

cut -d "_" -f 1

You don't need a parachute to go skydiving. You need a parachute to go skydiving twice.


Acties:
  • 0 Henk 'm!

  • swbr
  • Registratie: Maart 2009
  • Nu online
in awk (gaat geen snelheidsprijzen winnen):

code:
1
awk -F_ '{print $1}'

If you try and take a cat apart to see how it works, the first thing you have on your hands is a non-working cat. -DNA


Acties:
  • 0 Henk 'm!

  • Tony L
  • Registratie: September 2005
  • Laatst online: 07-11-2015
Wow, thanks!!!

Het ziet er naar uit dat SED inderdaad de meest handige is voor mij, ik begrijp alleen nog niet goed waarom basic dingen niet werken.

code:
1
2
3
echo "abcd123" | sed 's/\([a-z]*\).*/\1/'

Resultaat: abcd


Alleen als ik de nummers wil behouden werkt het niet...

code:
1
2
3
echo "abcd123" | sed 's/\([0-9]*\).*/\1/'

Resultaat: <niets>


Wordt [0-9]* niet ondersteund door SED?

PSN: Norfirin


Acties:
  • 0 Henk 'm!

  • NMe
  • Registratie: Februari 2004
  • Laatst online: 09-09 13:58

NMe

Quia Ego Sic Dico.

De *NIX-commanline is geen programmeertaal.

PRG>>NOS

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


Acties:
  • 0 Henk 'm!

  • VyperX
  • Registratie: Juni 2001
  • Laatst online: 14-08 13:04
Tony L schreef op woensdag 23 maart 2011 @ 12:13:
[...]
Alleen als ik de nummers wil behouden werkt het niet...

code:
1
2
3
echo "abcd123" | sed 's/\([0-9]*\).*/\1/'

Resultaat: <niets>


Wordt [0-9]* niet ondersteund door SED?
Uh oh... dit wordt mogelijk een crash-course in Reguliere expressies.

In je expressie zoek je naar een aantal nummers: '([0-9]*)', gevolgd door iets anders: '.*'.
Daar match "abcd123" niet op, omdat hier de nummers niet als eerste staan De string "123abc" zou wel matchen. Als je de twee delen zou omdraaien: '.*([0-9]*)', dan zou "abcd123" wel matchen.

Reguliere expressies zijn een erg krachtige tool, maar ze zijn niet erg intuitief of makkelijk.

My Dwarf Fortress ASCII Reward: ~~@~~####,.".D",.B""


Acties:
  • 0 Henk 'm!

  • Tony L
  • Registratie: September 2005
  • Laatst online: 07-11-2015
Ik denk dat ik wat basis concepten niet goed begrijp.

code:
1
2
3
4
5
find ./ -name '*0000*.txt' 

Resultaat:
.//10000_bestand.txt
.//20000_bestand.txt


Dit voer ik aan SED op de onderstaande manier:

code:
1
2
3
4
5
find ./ -name '*0000*.txt' | sed 's/[0-9]*//g'

Resultaat:
.//_bestand.txt
.//_bestand.txt


Dit is goed, geeft aan dat [0-9]* gevonden wordt! Alleen als ik dan //1 zou doen aan het einde, verwacht ik dat alleen deze groep wordt geprint!

code:
1
2
3
4
5
find ./ -name '*0000*.txt' | sed 's/\([0-9]*\)//1'

Resultaat:
.//10000_bestand.txt
.//20000_bestand.txt


Alleen zoals je ziet wordt alles geprint.. Zelfs het onderstaande werkt niet.

code:
1
2
3
4
5
find ./ -name '*0000*.txt' | sed 's/\([0-9]*\)/\1/'

Resultaat:
.//10000_bestand.txt
.//20000_bestand.txt

PSN: Norfirin


Acties:
  • 0 Henk 'm!

  • Tony L
  • Registratie: September 2005
  • Laatst online: 07-11-2015
VyperX schreef op woensdag 23 maart 2011 @ 13:10:
[...]


Uh oh... dit wordt mogelijk een crash-course in Reguliere expressies.

In je expressie zoek je naar een aantal nummers: '([0-9]*)', gevolgd door iets anders: '.*'.
Daar match "abcd123" niet op, omdat hier de nummers niet als eerste staan De string "123abc" zou wel matchen. Als je de twee delen zou omdraaien: '.*([0-9]*)', dan zou "abcd123" wel matchen.

Reguliere expressies zijn een erg krachtige tool, maar ze zijn niet erg intuitief of makkelijk.
De * van .* geeft toch aan dat er 0 of meer matches mogelijk zijn? Dan zou hij abc123 gewoon moeten vinden. Als ik er een + (1 of meer) van had gemaakt dan zou het logisch zijn dat er geen match werd gevonden.


EDIT :

Waarom geeft hij in het onderstaande voorbeeld alleen de nummers weer? Er wordt toch aangegeven dat hij op alfabetische karakters moet zoeken?

code:
1
2
3
4
echo "abc123" | sed 's/\([a-z]*\)//1'

Resultaat:
123


Waarom geeft hij in het onderstaande voorbeeld alles weer als ik alleen aangeef dat hij de eerste groep moet weergeven?

code:
1
2
3
4
echo "abc123" | sed 's/\([a-z]*\)/\1/'

Resultaat:
abc123

[ Voor 21% gewijzigd door Tony L op 23-03-2011 13:33 ]

PSN: Norfirin


Acties:
  • 0 Henk 'm!

  • blaataaps
  • Registratie: Juli 2001
  • Niet online
Tony L schreef op woensdag 23 maart 2011 @ 13:23:


Waarom geeft hij in het onderstaande voorbeeld alleen de nummers weer? Er wordt toch aangegeven dat hij op alfabetische karakters moet zoeken?

code:
1
2
3
4
echo "abc123" | sed 's/\([a-z]*\)//1'

Resultaat:
123
Sinds wanneer zitten de cijfers in het alfabet?
Waarom geeft hij in het onderstaande voorbeeld alles weer als ik alleen aangeef dat hij de eerste groep moet weergeven?

code:
1
2
3
4
echo "abc123" | sed 's/\([a-z]*\)/\1/'

Resultaat:
abc123
Je geeft aan dat hij de eerste groep moet vervangen door de eerste groep, het lijkt mij logisch dat er dan niks verandert..

offtopic:
sed en grep spel je trouwens gewoon met kleine letters, niet als SED en GREP..

[ Voor 6% gewijzigd door blaataaps op 23-03-2011 15:04 ]


Acties:
  • 0 Henk 'm!

  • Tony L
  • Registratie: September 2005
  • Laatst online: 07-11-2015
blaataaps schreef op woensdag 23 maart 2011 @ 15:02:
Sinds wanneer zitten de cijfers in het alfabet?
De groep staat toch om ([a-z]*) heen en met //1 wil je toch dat hij de eerste groep weergeeft? Ik zou dus verwachten om de letters te zien en niet de getallen.
blaataaps schreef op woensdag 23 maart 2011 @ 15:02:
Je geeft aan dat hij de eerste groep moet vervangen door de eerste groep, het lijkt mij logisch dat er dan niks verandert..
Sinds wanneer zitten de cijfers ook bij [a-z]?? De eerste groep is toch alleen ([a-z]*). Of zie ik iets over het hoofd?
blaataaps schreef op woensdag 23 maart 2011 @ 15:02:
offtopic:
sed en grep spel je trouwens gewoon met kleine letters, niet als SED en GREP..
Ok, thanks! :)

PSN: Norfirin


Acties:
  • 0 Henk 'm!

  • blaataaps
  • Registratie: Juli 2001
  • Niet online
Tony L schreef op woensdag 23 maart 2011 @ 16:36:
[...]


De groep staat toch om ([a-z]*) heen en met //1 wil je toch dat hij de eerste groep weergeeft? Ik zou dus verwachten om de letters te zien en niet de getallen.
Je moet of veel zorgvuldiger werken, of lezen hoe reguliere expressies eigenlijk werken.
In je 2e voorbeeld geef je al aan dat de syntax voor backreferences (de 'groepen') met een \ gaat, en niet met een /, en in dit voorbeeld verzin je syntax door achter een lege replace zomaar een '1' te gooien (op deze manier geeft je alleen maar aan de hoeveelste instantie hij van het te vervangen stuk hij moet pakken, dat heeft niks met backreferences te maken, vergelijk "echo aa | sed 's/a/b/1'" en "echo aa | sed 's/a/b/2'" ).
Sinds wanneer zitten de cijfers ook bij [a-z]??
Niet, maar dat blijkt ook nergens uit.
De eerste groep is toch alleen ([a-z]*). Of zie ik iets over het hoofd?
Je zegt "vervang de 1e groep door de 1e groep", en dat is precies wat er gebeurt, waarom zou hij iets met de cijfers doen? :)

Ik weet niet of je de beschikking over windows hebt, maar http://weitz.de/regex-coach/ is een programma die realtime en grafisch helpt bij reguliere expressies.

[ Voor 10% gewijzigd door blaataaps op 23-03-2011 17:08 ]


Acties:
  • 0 Henk 'm!

  • H!GHGuY
  • Registratie: December 2002
  • Niet online

H!GHGuY

Try and take over the world...

Waarom gaat iedereen meteen met een kanon (awk/sed/grep) op een mug schieten?

code:
1
find . -name '*.txt' | cut -d_ -f1

ASSUME makes an ASS out of U and ME


Acties:
  • 0 Henk 'm!

  • blaataaps
  • Registratie: Juli 2001
  • Niet online
H!GHGuY schreef op woensdag 23 maart 2011 @ 19:39:
Waarom gaat iedereen meteen met een kanon (awk/sed/grep) op een mug schieten?

code:
1
find . -name '*.txt' | cut -d_ -f1
Omdat ik het begin van het topic nog niet gelezen had :)

Acties:
  • 0 Henk 'm!

  • Rainmaker
  • Registratie: Augustus 2000
  • Laatst online: 14-07-2024

Rainmaker

RHCDS

En, als ik het goed begrepen heb, kan het zo ook:

code:
1
find . -name '*.txt' -exec grep -liE '<zoektext>' {}\; |  cut -d_ -f 1


Die extra pipe kost je alleen maar een file descriptor :)

We are pentium of borg. Division is futile. You will be approximated.


Acties:
  • 0 Henk 'm!

  • Tony L
  • Registratie: September 2005
  • Laatst online: 07-11-2015
H!GHGuY schreef op woensdag 23 maart 2011 @ 19:39:
Waarom gaat iedereen meteen met een kanon (awk/sed/grep) op een mug schieten?

code:
1
find . -name '*.txt' | cut -d_ -f1
Dan krijg ik nog steeds niet het juiste terug;

code:
1
2
.//10000
.//20000
blaataaps schreef op woensdag 23 maart 2011 @ 17:05:
[...]
Je moet of veel zorgvuldiger werken, of lezen hoe reguliere expressies eigenlijk werken.
Het probleem is niet zo zeer reguliere expressies, meer hoe sed er precies mee om gaat.
blaataaps schreef op woensdag 23 maart 2011 @ 17:05:
In je 2e voorbeeld geef je al aan dat de syntax voor backreferences (de 'groepen') met een \ gaat, en niet met een /, en in dit voorbeeld verzin je syntax door achter een lege replace zomaar een '1' te gooien (op deze manier geeft je alleen maar aan de hoeveelste instantie hij van het te vervangen stuk hij moet pakken, dat heeft niks met backreferences te maken, vergelijk "echo aa | sed 's/a/b/1'" en "echo aa | sed 's/a/b/2'" ).
Ahhh ik denk dat ik dat begrijp. Hij zoekt m.b.v. de reguliere expressie WAT hij moet vervangen... Stom!
blaataaps schreef op woensdag 23 maart 2011 @ 17:05:
Je zegt "vervang de 1e groep door de 1e groep", en dat is precies wat er gebeurt, waarom zou hij iets met de cijfers doen? :)
Bedankt voor de verheldering! Ik blijf het lastig vinden om precies te begrijpen wat sed doet.

Stel dat ik de volgende query heb:

code:
1
2
3
4
echo "abc123" | sed 's/[0-9]*/test/'

Resultaat:
testabc123


Waarom krijg ik dan testabc123 terug?? Ik geef toch aan dat ik alles wat matched met [0-9]* moet vervangen met test? Waarom krijg ik dan niet abctest terug?

PSN: Norfirin


Acties:
  • 0 Henk 'm!

  • Bart
  • Registratie: Februari 2001
  • Laatst online: 07:55
Er moet een . tussen:

$ echo "abc123" | sed 's/[0-9].*/test/'
abctest

I'm not deaf, I'm just ignoring you.


Acties:
  • 0 Henk 'm!

  • ajvdvegt
  • Registratie: Maart 2000
  • Laatst online: 27-09 18:28
En als je gaat werken met 'find' en 'xargs', ga je gaat vast tegen bestandnamen met spaties erin aanlopen. Dit ('-print0' en '-0') is vast de oplossing:
code:
1
find . -name '*.txt' -print0 | xargs -0 grep -l -i -E '(zoeken op )(tekst|text)'

I don't kill flies, but I like to mess with their minds. I hold them above globes. They freak out and yell "Whooa, I'm *way* too high." -- Bruce Baum


Acties:
  • 0 Henk 'm!

  • Tony L
  • Registratie: September 2005
  • Laatst online: 07-11-2015
Bart schreef op woensdag 23 maart 2011 @ 21:51:
Er moet een . tussen:

$ echo "abc123" | sed 's/[0-9].*/test/'
abctest
Dat werkt maar het zou niet hoeven naar mijn idee... [0-9]* moet nul of meerdere getallen matchen. Maakt sed gebruik van de "normale" regex syntax?

PSN: Norfirin


Acties:
  • 0 Henk 'm!

  • deadinspace
  • Registratie: Juni 2001
  • Laatst online: 03-10 18:29

deadinspace

The what goes where now?

Allemaal leuk die sed/cut/awk oplossingen, maar niemand die opmerkt dat de aanpak met grep van de topicstarter gewoon goed is, op een heel klein foutje na :P

Om eerlijk te zijn zou ik dit probleem zelf waarschijnlijk ook met grep oplossen.
Tony L schreef op woensdag 23 maart 2011 @ 11:27:
Ik had het idee om er weer een pipe (|) achter te zetten:
find ./ -name '*.txt' | xargs grep -l -i -E '(zoeken op )(tekst|text)' | xargs grep -l -i -o -E '[0-9]*'


Echter geeft dit niet het gewenste resultaat.
Heeft iemand enig idee wat ik moet doen om dit mogelijk te maken?
Ja, de -l in de tweede grep weglaten ;)

De tweede grep leest namelijk maar één "file" uit, namelijk zijn standard input welke via de pipe de uitvoer van de vorige grep krijgt. Met -l zal die tweede grep dus melden "Ja! standard input matcht je expressie!", waar je helemaal niks aan hebt.

De filenames uit de eerste grep zijn voor de tweede grep geen filenames meer, het is simpelweg tekst geworden.

Overigens kun je éénletterige opties (die geen argumenten verwachten) aan elkaar plakken na een enkel streepje, en is "egrep" een soort alias voor "grep -E". Je eerste grep-commando zou je dus ook als volgt kunnen schrijven:
% egrep -li '(zoeken op )(tekst|text)'

Oh, en als je [cmd] blokken voor je commando's en hun uitvoer gebruikt is het wat leesbaarder voor ons ;)
ajvdvegt schreef op woensdag 23 maart 2011 @ 21:57:
En als je gaat werken met 'find' en 'xargs', ga je gaat vast tegen bestandnamen met spaties erin aanlopen. Dit ('-print0' en '-0') is vast de oplossing:
code:
1
find . -name '*.txt' -print0 | xargs -0 grep -l -i -E '(zoeken op )(tekst|text)'
Dat zijn momenten dat je blij bent dat je zsh gebruikt:
% egrep -li '(zoeken op )(tekst|text)' **/*.txt

[ Voor 29% gewijzigd door deadinspace op 23-03-2011 23:05 ]


Acties:
  • 0 Henk 'm!

  • Tony L
  • Registratie: September 2005
  • Laatst online: 07-11-2015
Thanks deadinspace! Dat ga ik morgen op mijn gemak eens bekijken.

Wat ik nog niet goed begrijp is dat het regex technisch gewoon niet klopt wat sed doet... Gooi de volgende regex en test data eens in http://regexpal.com/

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Regex:
[^0-9]*

Test Data:
.//13059_bestand.txt
.//13060_bestand.txt
.//13061_bestand.txt
.//13075_bestand.txt
.//13080_bestand.txt
.//13092_bestand.txt
.//13093_bestand.txt
.//13099_bestand.txt
.//13100_bestand.txt
.//13102_bestand.txt
.//13103_bestand.txt


De [^0-9]* draait het om, dus ik zoek alles wat GEEN getal is. Als ik dit met sed zou vervangen met niets dan zou het toch moeten werken??

echo ".//123456_bestand.txt" | sed 's/[^0-9]*//'
123456_bestand.txt


Waarom haalt ie dan alleen .// weg en de rest niet! Ik begrijp er echt helemaal niets meer van.

PSN: Norfirin


Acties:
  • 0 Henk 'm!

  • CAPSLOCK2000
  • Registratie: Februari 2003
  • Laatst online: 02-10 22:42

CAPSLOCK2000

zie teletekst pagina 888

Tony L schreef op donderdag 24 maart 2011 @ 00:24:
echo ".//123456_bestand.txt" | sed 's/[^0-9]*//'
123456_bestand.txt


Waarom haalt ie dan alleen .// weg en de rest niet! Ik begrijp er echt helemaal niets meer van.
Zodra sed de '1' tegenkomt dan eindigt de regexp. En dan vindt sed dat ie z'n ding gedaan heeft en stopt er mee.
Het commando 's' kent de optie 'g' om niet te stoppen maar door te gaan:

echo ".//123456_bestand.txt" | sed 's/[^0-9]*//g'
123456

This post is warranted for the full amount you paid me for it.


Acties:
  • 0 Henk 'm!

  • Tony L
  • Registratie: September 2005
  • Laatst online: 07-11-2015
CAPSLOCK2000 schreef op donderdag 24 maart 2011 @ 00:53:
[...]


Zodra sed de '1' tegenkomt dan eindigt de regexp. En dan vindt sed dat ie z'n ding gedaan heeft en stopt er mee.
Het commando 's' kent de optie 'g' om niet te stoppen maar door te gaan:

echo ".//123456_bestand.txt" | sed 's/[^0-9]*//g'
123456
Dat had ik inderdaad nodig!! _/-\o_

PSN: Norfirin


Acties:
  • 0 Henk 'm!

  • H!GHGuY
  • Registratie: December 2002
  • Niet online

H!GHGuY

Try and take over the world...

Tony L schreef op woensdag 23 maart 2011 @ 21:45:
[...]
Dan krijg ik nog steeds niet het juiste terug;
code:
1
2
.//10000
.//20000
Wat verhindert je om de man page van find erop na te slaan.

Bekijk eens de -printf optie en gebruik hem met de %f vlag.

ASSUME makes an ASS out of U and ME

Pagina: 1