30
« : 17.06.13 - klo:06.31 »
Tämä sed-ohje on vielä keskeneräisempi kuin tuo awk-ohje seuraavassa.
Ohjelma sed muokkaa ohjelmallisesti sille annettua tekstiä.
- käsiteltävä teksti on usein tiedostoissa. jokaisen tiedoston rivit on numeroitu, sitä ei vain aina näytetä. Rivit numeroidaan
järjestyksessä ykkösestä alkaen.
- käsiteltävä voidaan toimittaa sed:iin:
1. sed määrittelyt tiedostonNimi
2. "tulostus jollain konstilla" | sed määrittelyt
tai kyllähän niitä kikkoja löytyy mutta ne selviävät kyllä kun semmoinen tulee eteen
- sed käy yksitellen läpi tiedoston kaikki rivit alkaen ykkösestö ja siitä järjestyksessä eteenpäin. sed:issä voidaan kuitenkin antaa
osoitteita. osoitteet ovat joko rivinumeroita tai /teksti/. jos osoitteita on vain yksi niin muokkaaminen koskee vain sitä ja jos
osoitteita on kaksi niin muokataan rivejä niiden välissä.
- jos toiminta juuttuu jonnekin kun ollaan sed:issä paina CNTRL-c.
- tiedoston teksti tulee näytölle jokatapaukseessa. Jos hjaluat muutoksen tallentuvan tiedostoon niin kirjoita: sed -i ...
- jos et halua tekstimuutoksen kirjoittuvan näytölle niin kirjoita: sed -n ...
- ihan rauhassa voi käskeä: sed 's/apu/apua/g' sillä se ei päädy päättymättömään looppiin.
- mikäli peräkkäin on useampia sed:ejä niin sana sed kirjoitetaan vain kerran ja käskyt erotetaan kuten seraavassa esimerkissä:
sed -e '/^#/d' -e 's/#.*$//' # poistaa kommenttirivit ja kommentit pitemmältä
Esimerkkejä:
sed 's/mikä/miksi/g' # muuttaa jokaisen sanan:mikä muuttaminen sanaksi:miksi
sed -i 's/mikä/miksi/g' # sama muutos, mutta tiedoston teksti muutetaan myös
sed -n 's/mikä/miksi/g' # sama muutos, mutta tiedoston teksti muutetaan niin ettei se tule näytölle
sed -ni 's/mikä/miksi/g' # sama muutos, mutta tiedoston teksti muutetaan myös eikä näytölle tule mitään
sed 's/.*mikä.*/miksi/g' # koko lauseen jossa sana:mikä on muuttaminen sanaksi:miksi
sed '/baz/s/foo/bar/g' # tiedostossa tehdään muutokset vain riveillä joissa on jossain paikassa: baz
sed '/baz/!s/foo/bar/g' # tiedostossa tehdään muutokset vain riveillä joissa ei ole jossain paikassa: baz
sed 's/^ *//g;s/ *$//g' # Poistaa välilyönnit tiedoston riveiltä edestä ja perästä. Tästä
# näkee myös kuinka kaksi perättäistä sed:iä yhdistetään
sed 's/^ *//g' # poistaa välilyönnit tiedoston rivien alusta
sed "s/^.//g" # poistaa tiedoston jokaiselta riviltä ensimmäisen merkin, mikä se sitten onkin
sed -e '/^$/d # poitaa tiedoston tyhjät rivit
sed -i 6,66d # poistaa tiedoston rivit 6-66
sed -e '/^#/d' -e 's/#.*$//' # poistaa kommenttirivit ja kommentit pitemmältä riveistä
sed '4!d' # tulosta ainoastaan tiedoston rivin 4 . Sama kuin sed -n '4p' tai: awk 'NR==4'
sed '8,12!d' # tulosta rivit 8-12
sed '8,12d' # tulostaa kaikkimmuut rivit paitsi 8-12
sed -i.bak 's/mikä/miksi/g' # tee backup ennenkuin talletat muutokset
sed 's/:/\n/g' <<< $PATH # tämä tulostaa käyttöjärjestelmän polut kukin omalle riville
sed "s:/old/direcory/:/new/directory/:" # sedissä / toimii kenttien jakajana. Tällätavoin jakajaksi voi määrätä kaksoispisteen
sed -n -e '1,/etsittävä ilmaisu/p' # poista loput rivit löydettyään ilmoitetun lukumäärän etsittyä
sed 's/[![0-9]][0-9]:/"\ "&/g') # &-merkin kohdalle tulee se tekstijono mikä [![0-9]][0-9]: määräämässä etsinnässä löytyi
sed 's/^ */"/g;s/ *$/"/g' # lisää tiedoston jokaisen rivin alkuun lainausmerkki ja loppuun myös.
sed -e :a -e '/$/N;s/\n/ /;ta' # tulostaa kaiken yhteen riviin
sed -e 's/^\(.*\) .*/\1/' # poistaa viimeisen sanan jokaiselta riviltä
sed -e '/^[<space><tab>]*$/d' somefile # tulostaa tiedoston jättäen pois rivit jotka ovat pelkkää välilyöntia tai tabulaattoria
sed 'G' # tulosta tiedosto lisäten tyhjän rivin jokaisen tekstirivin perään
sed -n '1!G;h;$p' # tulosta rivit käänteisessä järjestyksessä. Käskyssä käsitellään buffereita
sed -e '/./{H;$!d;}' -e 'x;/hakusana/!d' # tulosta jokainen kappale jossa on määriteltävä-hakusana
sed '/kortti/alisätty_rivi' # lisää rivi jolla lukee: lisätty_rivi jokaisen rivin jälkeen jolla lukee jossain kortti
sed -e 's/'$(echo "octal-value")'/replace-word/g' # kontrollimerkkien poistaminen
sed 's/mikä/miksi/g' tiedosto1 > tiedosto2 # lukee tiedosto1:stä, tekee muutokset ja kirjoittaa tiedosto2:een
sed 's/^./tekstiä /g' # kirjoittaa jokaisette ei-tyhjälle riville sanan: tekstiä
ja perään kirjoittaa sen tekstin joka rivillä ennen oli
echo abcd1eeee | sed 's/\([a-z]*\).*/\1/' # tulostaa abcd ja jättää ensimmäisen numeron ja sen jälkeiset pois
echo "eka toka kolmas" | sed 's/\([[:graph:]]*\).*/\1/' # tulostaa eka ja jättää loput sanat pois.
echo "1eka2 toka kolmas" | sed 's/\([[:graph:]]*\) \([[:graph:]]*\)/\2 \1/' # vaihtaa ensimmäisen ja toisen sanan
tiedostojärjestemän osassa kaikissa tiedostoissa sanan muuttaminen toiseksi:
find tiedostojärjestelmän_osa -type f -exec sed -i "s/mikä/miksi/g" {} \;
Grep käy sille annetun tekstin läpi rivi kerrallaan järjestyksessä alusta loppuun ja tulostaa näytölle kaikki ne rivit joilta etsitty löytyy.
Grep on yleensä määrätty värittämään hakutermin tulostuksensa jokaisella rivillä. Jos näin ei ole voi kirjooittaa 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" .
**
Grep tuntee ennaltamäärätyn merkkin, jossa merkki kuuluu johonki seuraavista ryhmistä:
[[:alnum:]]->[[A-Za-z0-9]] [[:alpha:]]->[A-Za-z] [[:blank:]]->välilyönti tai TAB [[:cntrl:]]->jokin kontrollimerkki
[[:digit:]]->[0-9] [[:graph:]]->ASCII 33 - 126 [[:lower:]]->[a-z] [[:print:]]->ASCII 32 - 126 ja välilyönti
[[:space:]]->välilyönti ja TAB [[:upper:]]->[A-Z] [[:xdigit:]]->[0-9A-Fa-f]
- skandit taitaa olla mukana vaikei niistä puhutakaan; tämä näkyy käskystä: echo "AAAAAAAAAAAAAAAAAö" | grep [[:lower:]]
- joskus hyväksytään kaksois-sulun paikalla vain yksi sulku
**
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 korkeintaan m-kertaa
\< ja \> hakusana rajoittuu tyhjään (=joko välilyöntiin tai rivin alkuun/loppuun)
[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:]]
**
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ä.
Seuraavassa luettelo yleisimmistä optioista:
r etsintäpaikka on kansio ja sieltä etsitään rekursiivisesti s ei tulosteta edes varoitusviestejä
c vain löytöjen lukumäärä tulostetaan v poista hakutuloksista ne joissa etsitty on osana
h tulostaa sen tekstirivin jolta etsitty löytyy w oleta etsittävän alkuun ja loppuun \< ja \>
l tulostaa sen tiedoston nimen josta etsitty löytyy n tulostaa myös miltä riviltä etsitty löytyi
i etsittäessä ei huomioida kirjainkokoa m <luku> lopeta luku osumien jälkeen
F etsitään kirjaimiltaan juuri sellaista mikä etsittäväksi määrättään
e optiot on nyt kirjoitettu ja haettava seuraa vaikka se alkaisi miinus-merkillä
E ota käyttöön laajennoksia, mm. \ ei tarvita; siis esimerkiksi kun etsit "placeholdereita" niin etsittävä on: grep -E {} mistä_etsittään
A <numero> tai: -B <numero> tai: -C <numero> tulosta <numero> riviä haetun rivin edestä, jäljestä yai molemminpuolin
**
ESIMERKKEJÄ:
grep "[0-9]\{5\}" # etsii yli viisinumeroista sanaa jonka jokainen merkki on 0-9
# täsmälleen viisinumeroiset: grep "\<[0-9]\{5\}\>"
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ä
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 -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 -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
**
HUOMAUTUKSIA:
- jostain syystä kun etsii ilmaisua: -exec kirjoitetaan hakusana: \\-exec
- 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: -e tekstialussa -e tekstilopussa
- 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.
- 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.