http://forum.ubuntu-fi.org/index.php?topic=303.msg323961#msg323961

Grep-lauseen muoto: grep mitä_etsitään mistä_etsitään
- mitä_etsitään on usein joku sana. Mutta se voi olla myös regex: esimerkiksi kun etsitään aakkosta niin grep on: grep [0-9]. Katso ohjeiden kohta: regular expression 
**
Grep käy sille annetun tekstin läpi rivi kerrallaan ja jokaisen rivin merkki kerrallaan järjestyksessä alusta loppuun ja tulostaa näytölle kaikki mikä sopii regex:ään. Tekstissä oleva rivinsiirto siirtyy sellaisenaan ellei toisin määrätä. 
Siten käsky: grep tiedosto [a-z] tulostaa tekstissä olevat pienet kirjaimet riviluvun pysyessä samana; mikäli rivillä ei ole yhtään pientä kirjainta tulostuu kuitenkin rivinsiirto.
      Käsky: grep tiedosto [a-z]* tulostaa siis aivan samallatavalla.
**
Grep on yleensä määrätty värittämään hakutermin tulostuksensa jokaisella rivillä. Jos näin ei ole voi kirjoittaa grep-käskyn perään:
--color=always. Tai jos et halua väriä niin kirjoita grepin jälkeen: --color=none
**
Etsittävä voidaan antaa grep:ille kahdella keinolla:
1. tulosta_etsittävä_teksti_jotenkin | grep mitenkä_etsitään       
2. grep mitenkä_etsitään  sen_tiedoston_nimi_josta_etsitään   
- siis yksinkertainen haku on muotoa: echo "hhh 58 jjjj" | grep 58       tai: grep "kortti" tiedosto
- BASH:kin yrittää tulkita tuon mitenkä_etsitään ja joskus se ei ole toivottavaa. Tältä tulkinnalta voi suojautua kirjoittamalla
  'mitenkä_etsitään'. Joskus kuitenkin BASH:n toiminta on toivottavaa. Silloin kirjoitetaan: "mitenkä_etsitään"  .  
**
- skandit taitaa olla mukana vaikei niistä puhutakaan; tämä näkyy käskystä: echo "AAAAAAAAAAAAAAAAAö" | grep [[:lower:]]
**
grepin kytkimistä (optiot):
Optioiden alku on grep-sanan jälkeisen välilyönnin jälkeinen miinusmerkki. Jos miinus on jossain muualla ei se ole merkki optioiden 
alkamisesta. Optioita voidaan kirjoittaa vaikka kuinkamonta ja vain tuo yksi miinusmerkki tarvitaan; vaikka jos haluaa niin jokaisen 
option eteen voi kirjoittaa <välilyönti>miinusmerkki. Joskus tarvitseekin kertoa grep:ille että "nyt ne optiot loppu". Tällöin viimeiseksi
optioksi kirjoitetaan e. Senjälkeistä käsitellään etsittävän määrityksenä vaikka se alkaisi miinusmerkillä.  

-r  etsitään rekursiivisesti                          -s  ei anneta varoitusviestejä                      -c  vain löytöjen lukumäärä tulostetaan 
-h  tulostaa sen tekstirivin jolta etsitty löytyy     -w  oleta etsittävän alkuun ja loppuun \< ja \>     -v  poista hakutuloksista ne joissa etsitty on osana   
-l  tulostaa sen tiedoston nimen josta etsitty löytyy -n  tulostaa myös miltä riviltä etsitty löytyi      -i  etsittäessä ei huomioida kirjainkokoa     
-F  etsitään kirjaimiltaan juuri sellaista mikä etsittäväksi määrättiin, esimerkiksi merkkiä: *           -m 1    vain ensimmäinen osuma tulostetaan
-e  optiot on nyt kirjoitettu ja haettava seuraa vaikka se alkaisi -                                      -o kirjoita jokainen löydetty omalle rivilleenja jätä ei-valitut pois->tekee hausta lazy:n
-P  regular expressionissa: '\w'->sana '\d\'->numeroryhmä 
-x  etsitään kokonaista lausetta
-E  ota käyttöön laajennoksia, mm. \ ei tarvita; siis esimerkiksi kun etsit find-käskyn "placeholdereita" niin etsittävä on: grep -lrE {} mistä_etsittään
-A <numero>  tai: -B <numero> tai: -C <numero>      tulosta <numero> riviä haetun rivin edestä, jäljestä tai molemminpuolin
**
grepin AND_
grep -E 'malli1.*malli2' file.txt # tässä järjestyksessä
grep -E 'malli1.*malli2|malli2.*malli1' file.txt # haetut voivat olla missähyvänsä järjestyksessä
grep 'malli1' file.txt | grep 'malli2'           # haetut voivat olla missähyvänsä järjestyksessä
**
hakutermejä voidaan yhdistää kirjoittamalla ne peräperään
hakutermit voidaan liittää yhteen myös tai-toiminteella kirjoittamalla niiden väliin merkki |
suluilla voidaan muuttaa järjestystä 

-Po 'tätä_haetaan(?=.*tämän_täytyy_olla_perässä_mutta_tätä_ei_valita)'  # haku- ja kelpuutus-sanojen välissä saa olla tekstiä
-Po 'tätä_haetaan(?!tämä_ei_saa_olla_perässä)'                          # haku- ja esto-sanojen välissä ei saa olla tekstiä
-Po '(?<=tämän_täytyy_olla_edessä_mutta_tätä_ei_valita)tätä_haetaan'    # haku- ja kelpuutus-sanojen välissä ei saa olla tekstiä
-Po 'tätä_haetaan(?<!tämä_ei_saa_olla_edessä)'                          # haku- ja esto-sanojen välissä saa olla tekstiä
-Po '(?<=teksti_edessä).*(?=teksti_perässä)'                            # tulostaa tekstin joka on hakuavaimien välissä. Myös: grep -Po '(?<=:).*(?=:)' onnistuu
-o teksti_edessä.*tekstiperässä                                         # sama kuin edellinen, mutta teksti_edessä ja teksti_perässä kirjoitetaan myös
-Poz  '(?ism:^BEGIN.*?END)'                # i=älä välitä merkkikoosta, s=begin ja end voivat olla eri riveillä, m=merkin:^ käyttö sallitaan lukitsemaan begin rivin alkuun 

lohkojen valinta:
 

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

Kun grep:lle annetaan käsiteltäväksi teksti alkaa se tutkia sille annettua tekstiä alkaen merkistä 1 jatkaen siitä merkki kerrallaan kohti loppua ja tulostaa jokaisen merkin joka sopii regex:ään ja rivinsiirron kun:
1. merkki ei sovi regex:ään ja grep:illä on kytkin -o.
2. grep:in kytkin -o on asetettu eikä olla *-alueella
- rivinsiirtoa ei tulosteta kun edellinen tulostettu on ollut rivinsiirto. 
Siten esimerkiksi:
1. echo juu | grep '[a-z]'    # tulostaa: juu 
2. echo juu | grep -o '[a-z]' # tulostaa:  
   j
   u
   u
3. echo "juu jaa" | grep -o '[a-z]*' tulostaa:
   juu
   jaa
- sillä ainoastaan välilyönnin kohdalla grep ei ole regex:än *-merkin alueella.
**

**
Kun haettavassa sanassa on joku seuraavista niin se tulkitaan kuvatulla tavalla:
?                paikalla voi olla yksi merkki tai sitten ei
.*               paikalla voi olla mielivaltainen määrän merkkejä, ja sen paikalla ei välttämättä täydy olla merkkiä ollenkaan
+                paikalla voi olla mielivaltainen määrän merkkejä, ja sen paikalla täytyy olla vähintään yksi merkki
.                paikalla voi olla täsmälleen yksi merkki. 
[abcde]          paikalla voi olla täsmälleen yksi mukanaolevista merkeistä
[^abcde]         paikalla voi olla mikähyvänsä muu merkki paitsi jonku esitetyistä merkeistä. Merkkiä ! voi käyttää ^ paikalla.
[a3][c5]         paikalla voi olla joku merkkiryhmistä  ac,a5,3c,35
-E haettava{n\}   haettava kertautuu täsmälleen n-kertaa # tämä ja seuraavat 3 eivät toimi niin kuin ihminen ymmärtää vaan niin kuin kone ymmärtää
-E haettava{n,\}  haettava kertautuu korkeintaan n-kertaa
-E haettava{n,m\} haettava kertautuu jotakin n,m välillä
-E haettava{,m\}  haettava kertautuu nolla tai korkeintaan m-kertaa 
\< ja \>         hakusana rajoittuu tyhjään (=joko välilyöntiin tai rivin alkuun/loppuun)
\b               välilyönti tai rivin raja
\B               välilyönti mutta rivin raja ei kelpaa
[asdfg]          hakusana on mikähyvansä merkeistä asdfg (se ei siis etsi koko sanaa. Kun etsitään sanaa niin jätetään sulut pois). 
[a-g]            sama toisella tavalla
[^asdfg]         hakusana on mikähyvänsä muuta merkkiä kuin jotakin joukosta asdfg  . ! on sama kuin ^.
[[:digit:]]      hakusanaksi voi antaa minkähyvänsä ennaltamäärätyistä merkeistä; siis sillä paikalla on vain yksi merkki
                 esimerkiksi jos etsittävässä on kaksi numeroa niin periaatteessa se on: [[:digit:]][[:digit:]] ja mikäli merkkejä onkin määräämättömän 
                 monta niin [[:digit:]]*
**
mikäli grep:ille halutaan antaa jokin merkeistä:  ? + { | tai ( ihan normaalina merkkinä on sen eteen kirjoitettava \ 
**
ESIMERKKEJÄ:
grep "[0-9]\{5\}"                  # etsii yli viisinumeroista sanaa jonka jokainen merkki on 0-9 
grep '.'                           # tulosta tiedosto jättäen pois tyhjät rivit
grep "\<[0-9]\{5\}\>"              # täsmälleen viisinumeroiset; siis alku ja loppu joko välilyönti, rivinalku tai rivinloppu: 
grep [![:lower:]]                  # etsii onko sanassa jossain ainakin yksi pieni kirjain
grep [a-c]-ajokortti               # etsii a-, b- ja c-ajokortit mutta ei muita ajokortteja
grep [\ e]grep                     # etsii grep:in ja egrep:in muttei muita grepejä
grep '^\..*\.$'                    # etsittävä alkaa pisteellä ja loppuu pisteeseen ja välissä on jotain tekstiä.
grep -E ^a\|^b                     # etsii rivit jotka alkavat a:lla tai b:llä ( yksi tapa muodostaa OR/TAI )
grep -E '(ei mitään)|(none)'       # kumpaakaan sanaa ei saa löytyä tai kumpikin sana pitää löytyä
grep -E "a{2}"                     # etsittävässä täytyy olla peräkkäin vähintään 2 a:ta
grep -E -o ".{0,5}etsittävä.{0,5}" # tulostaa etsittävä:n edestä ja perästä korkeintaan 5 merkkiä, eikä kokoriviä
grep . tiedosto > tiedosto2        # kopioi tiedostosta tiedosto2:een jokaisen rivin jolla on tekstiä (=poistaa tiedosto:sta tyhjät rivit)
grep -v -e '^$'                    # poista tyhjät rivit
grep -C <riviluku> hakusana        # tulosta etsityn lisäksi edestä ja perästä riviluku riviä
grep -v "^#"                       # tulosta jättäen pois kommenttirivit
grep -e .doc -e .html              # grepin tai-funktio. Myös (.doc)|(.html) toimii.
grep '\<c...h\>'                   # etsii viisikirjaimisia sanoja jotka alkavat c:llä ja päättyvät h:hon. Esimerkki: grep '\<c...h\>' sanakirja
grep '[Ss]mug'                     # etsii kumpaakin sanoista: Smug ja smug 
grep '"smug"'	                   # etsii lainausmerkeussä olevaa sanaa "smug". Ilman lainausmerkkejä ei kelpaa. 
grep -- --                         # etsi kahta tai useampaa miinus-merkkiä
grep -o -b  "etsittävä" | awk -F: '{print $1}' # tulostaa etsittävän ensimmäisen merkin sijainti-numeron (=pos-käsky)
grep -Eio '([[:alnum:]_.-]+@[[:alnum:]_.-]+?\.[[:alpha:].]{2,6})' # tarkista onko kyse msähköposti-osoitteesta
grep -ircl --exclude=*.{png,jpg} "foo=" *
grep pattern -r --include="*.{cpp,h}" rootdir
grep "z-index" . --include=*.js --exclude=*js/lib/* --exclude=*.min.js # voi in/ex-cludeja olla samalla rivilläkin useampia 
grep -E "henkilö|varaus"           # etsii kummatkin, tai-funktio
grep -c ^                          # laskee riviluvun
grep -s /                          # ei ole sekundakonsti "permission denied" viestien estämiseksi 
grep -o '4[0-9]\{4,9\}'            # etsi numerosarjat jotka alkavat 4:llä jonka perässä on 4-9 numeroa
grep "\<[0-9].*[0-9]\>"            # etsii semmoista joka alkaa ja loppuu numerolla
egrep -v "^#|^$" /tiedosto         # tulosta tiedosto jättäen tyhjät- ja kommenttirivit pois
grep -oP '(?<=edessä).*(?=perässä)'  # tulostaa tekstin joka on hakuavaimien välissä
grep  "\<[0-9]\{5\}\>"             # kelpaa vain silloin kun luvun molemmin puolin on välilyönti tai tekstijonon alku tai loppu.
grep -E '(.)\1'                    # etsii löytyykö jokin merkki useaman kerran peräkkäin
grep -E '(.)\1{2}'                 # etsii löytyykö jokin merkki täsmälleen 3 kertaa peräkkäin
grep "([A-Za-z ]*)"                # etsii tekstejä jotka ovat ympäröity suluilla
grep -E "(copy)?right"             # etsii sanoja copyright tai right 
grep -E "free[^[:space:]]"         # etsii sanaa free(ja joku merkki joka ei kuitenkaan saa olla välilyönti); pelkkä sana free ei kelpaa     

käskyissä tyypiltään:  ps -ef | grep '[b]ash' on nuo hakasulut siksi että kun etsitään käskyä se toteutettaisiin muuten

grep -Po '(?:Tal.*\")[^\"]'          # etsii sanaa: Tal ja tulostaa kaiken tekstin: Tal <mitä hyvänsä> " <mitä hyvänsä> "
grep -Pow '(?:sin .*)[$\"\ \"]'      # tulostaa sanasta <välilyönti tai rivin alku>sin<välilyönti> alkaen seraavaan välilyöntiin. Argumentti saa
                                     # olla erotettu suluilla tai lainausmerkeillä
echo abcdefgaec | grep -oE 'a(b|e)c' # or-toiminto
grep -E 2\{3\}                       # etsii vähintään 3 2:ta peräkkäin
grep '\([0-9]\)\1'                   # etsii kahta peräkkäistä samaa numeroa; \1 on takaisinpäinviittaus niinkuin sed:issä
grep '\([0-9]\)\1\1'                 # etsii kolmea peräkkäistä samaa numeroa
grep -e '^\(abc\)\1$'                # etsii pelkästään : abcabc ja rivillä ei saa olla mitään muuta
grep "\([aeiou]\).\1"                # etsii onko sanassa kahta merkkiä ryhmästä aeiou; merkkien ei tarvitse sijaita peräkkäin 
grep .*[0-9][0-9][0-9][0-9].*/home/ /etc/passwd | cut -d: -f1 # lista koneen käyttäjistä
grep xyz abc.txt | while read -r line ; do echo jep; done   --- while read -r line ; do echo jees; done < <(grep xyz abc.txt)
grep \*                              # etsii tähteä
grep \*\\*                           # etsii kahta peräkkäistä tähteä; jokainen * lisää hakutermiin \\*
grep -P '<[^<>]+>'                   # etsi kaikki HTML-tagit 
grep -Po '(.*)\1'                    # tulosta peräkkäiset samat kirjaimet/joukot  
grep --color -E "kakkula|$" ~/koe    # tulosta koko tiedosto ja väritä etsitty kaikissa paikoissa
grep -Pzo '(?s)begin.*end'           # tulosta tekstirivin välistä begin-end. Mikäli etsittävässä on useampi begin/end-lohkoja laita (?sU). Ungreedy on vaarallinen.
cat -e /boot/grub/grub.cfg  | grep -Poz  '(?ism:BEGIN.*?END)' | sed 's/END/&\n/g' # lohkojen eroittaminen tiedostosta
grep -Pzo '(?s)(?<=begin).*(?=.*end) # tulosta lohko välistä begin-end korvaten begin-end rivit tyhjillä riveillä
grep -R koe1 ~/OMATSKRIPTIT          # tulosta tiedostot joista löytyy sana: koe1
grep -v '/\.'                        # suodata piilotiedostot pois
< /boot/grub/grub.cfg  grep menuentry# etsi tiedostosta sanat
- tiedostoissa on joskus epäkelpoja merkkejä. Tällöin esimerkiksi: cat /boot/grub/grub.cfg | tr -dc [[:graph:]]'\n' | grep -Pzoi '(?s)begin.*end'
export GREP_COLOR="01;32" # green; 31=red; 33=yellow; 34=blue; 35=purple

**
echo fdfdfalku..tarinaa..loppufdfvdvalku.*muutatarinaa..loppu | grep -o alku.*loppu # tulostaa: alku..tarinaa..loppu
echo "fdfdf<<..tarinaa..>>fdfvd<<..muuta tarinaa..>>" | grep -Po \<\<.*?\>\>        # tulostaa:
<<..tarinaa..>>
<<..muuta tarinaa..>>
**
echo "hi how are you " | grep -oP ".*"    # tulostaa: hi how are you
echo "hi how are you " | grep -oP ".*? "  # tulostaa:
hi 
how 
are 
you 
**
HUOMAUTUKSIA:

- jostain syystä kun etsii ilmaisua: -exec kirjoitetaan hakusana: \\-exec -> eka keno on BASH:ille ja toka grep:ille. Joskus kenoja on neljäkin.

- etsittäessä merkkijonoa jonka alku ja loppu tiedetään mutta siinä välissä olevaa ei tiedetä niin hakusana on: tekstialussa.*tekstiloppussa 
  tekstialussa ja tekstilopussa saavat olla eri riveillä. Joskus täytyykin painottaa että niiden täytyy olla samalla rivillä joten hakusana 
  onkin: grep -e tekstialussa -e tekstilopussamerkkityhmien
 
- etsittäessä merkkiä jolla on erikoismerkitys niin sen eteen tulee \. Siis esimerkiksi kun etsitään sanaa $-arvo niin hakusana on: \$-arvo 

- useimmat erikoismerkit menettävät erikoismerkityksensä merkkien []   tai: '' välissä

- jos hakusana on etsittävän rivin alussa kirjoitetaan hakusanan eteen ^ ja jos se on lopussa kirjoitetaan hakusanan perään $ . 
  Siis ^$ on tyhjä rivi. Mikäli merkki ^ on jossain muualla on se tavallinen merkki.grep -Pow '(?:cos\ .*)'

- nuo haut siis etsivät tiedoston sisällöstä. Kun etsit tiedoston nimestä niin käsky on esimerkiksi: find /home | grep "haettava"

- jos haluaa etsiä kahta sanaa samassa haussa onnisttu se käskyllä: egrep -w 'sana1|sana2' tiedosto

- grepin tulostuksesta voi muodostaa loopin: for i in /etc/profile.d/*.sh ; do ....; done

- oletetaanpa että koti-kansiossasi on skripti, jossa on käytetty käskyä tr hyvin erikoisella tavalla. Et muista missä se on ja haluaisit 
  löytää sen. Annettava käsky on: grep -r "\<tr" ~  . (= tr:n tulee olla joko rivin alussa tai sitä täytyy edeltää välilyönti) Jos tuon 
  \< jättää pois niin tulee tosipaljon "vääriä"" löytöjä.

- grepin toimintaan voidaan vaikutaa BASH:in ympäristömuuttujilla.

- grep:iä voidaa käyttää skripteissä myös siten, että skriptintoimintaa muutetaan senmukaan löytääkö grep jotakin vaiko ei. Tätä toimintaa 
  vastaava käsky on: [[ $( grep ... ) ]] && tee_jotain. Tässä on kylläkin sellainen vikamahdollisuus että jos onnistuu tekemän grepin niin 
  että se tekee virheen niin käsky suoritetaan aina. Siis joissakin tosi-harvinaisissa tapauksissa virheet pitää suunnata tiedostoon tai 
  tarkistaa ettei muuttujan $? arvo ole 2.

- grep:iä vastaava toiminta saadaan osittain aikaan: variable="kakkularatsis"; osa=rat; if [[ $variable =~ $osa ]]; then echo $variable; fi 

- grep -Po  "[0-9]*" <<<"test123*hhh55" # tulostaa kokonaisluvuista muodostuvat etumerkittömät numerosarjat omille riveilleen. Mikäli luvut voivat 
  olla liukulukuja niin esimerkiksi seuraavankaltainen rimpsu puree: echo "test+12.3e-3*e  eeeemelihhh-5e+5" | sed 's/e[a-z ]//g' | grep -Po  "[0-9.e+-]*"
  ; siis koko rotla: | sed 's/e[a-z ]//g' | grep -Po  "[0-9.e+-]*" on se valikoiva lause ja aina vakio.

- grep -Pow '(?:cos\ .*)' tulostaa lauseen siitä alkaen missä sana: cos on ja jos sanaa ei ole ei myöskään tulosteta mitään
  etsi teksti: tätä_haetaan niin saat lisää tämänkaltaisia esimerkkejä

- grep -a -B 25 -A 100 'Ohjeita skriptiajurin hakemiseksi' /dev/sdb2 > results.txt # etsi deletoitua kun olet bootannut toisella osiolla
 
- grep -Po '(?<=hakuavain1).*(?=hakuavain2)' # tulostaa tekstin joka on hakuavaimien (tag:ien)välissä

- echo 1234567890 | grep -oE "[[:digit:]]{1,5}" # tulostaa kaksi riviä: 12345 ja 67890; siis haku alkaa uudestaan heti kun edllinen ehto täyttyy

- var=1qa2ws3ed4rf; echo "${var//[![:digit:]]/}" # tulostaa 12345 joten voi sen tr:n kiertääkin

Use process substitution to create a keyword "file" that you can pass to grep via the -f option:

grep -f <(awk '{print $1}' tiedosto_jonka_kenttä1_sisältää_listan_sanoista_joita_etsitään_polun_tiedostoista) polku/*

grep -Po '(?<=<<).*(?=>>)' ~/tiedosto | awk '{split($0,a,"\n"); for (i = 1; i <= NF; i++) print length(a[i])}' # tagien välisten merkkiryhmien pituudet


