Ubuntu Suomen keskustelualueet
Ubuntun käyttö => Ohjelmointi, palvelimet ja muu edistyneempi käyttö => Aiheen aloitti: odysseus - 27.05.13 - klo:16.46
-
Eli siis kyse on siitä, että onko jotain valmista palikkaa joka tekee seuraavaa:
-etsii ja korvaa sanan (tmv) useasta tiedostosta (kaikista hakemistossa ja alihakemistoissa)
-tekee saman usealle etsi-korvaa parille yhdellä kertaa
Tämä voisi siis olla ohjelma (mieluiten komentoriviltä), joka lukee parametrina "etsi-korvaa" tiedoston ja sitten käsittelee parametrina annetun hakemiston ja sen alihakemistot (kaikki tiedostot).
Luettava etsi-korvaa input-tiedosto voisi olla vaikka muotoa:
ETSI=KORVAA
ETSI2=KORVAA2
JUUPAJUU=JOOPAJOO
...
Tai ihan mitä tahnansa vastaavaa.
Onko siis tiedossa tuommoista suoraan olemassa tai helpolla scriptillä tehtävissä? Itse rupesin jo ajattelemaan kaikkea liikaakin ja mietin, että ehkä C-preprocessor ja makefile tekisi tuon #define:illä, mutta menee hankalaksi. Pitääkö tässä vääntää tuo itse ohjelmaksi?
-
En jaksa ruveta vääntämään valmista ratkaisua, mutta awk:lla sellaisen tekeminen saattaisi olla melko yksinkertaista.
-
Ainakin yksi juttu sinun on tarkennettava, tarkoitatko sanoja vai merkkijonoja.
Meinaan on eri juttu korvata lauseesta ETSI sanana kuin merkkijonona.
Jos on sana ETSIpä niin pitäisikö tuostakinkin korvata merkkijono ETSI?
Jos kyse vain merkkijonopareista niin käyttäisin sanaparitiedostossa välilyöntiä erottimena ja
sitten vaan
while read e k
do
sed s/$e/$k/g -i kohdefile
done < sanaparitiedosto
Voisi toimiakin ;)
Ja tällaiseen skriptiin olisin valmis tekemään vaikka funktion tuosta sedisilmukasta...
-
Ainakin yksi juttu sinun on tarkennettava, tarkoitatko sanoja vai merkkijonoja.
Meinaan on eri juttu korvata lauseesta ETSI sanana kuin merkkijonona.
Jos on sana ETSIpä niin pitäisikö tuostakinkin korvata merkkijono ETSI?
Jos kyse vain merkkijonopareista niin käyttäisin sanaparitiedostossa välilyöntiä erottimena ja
sitten vaan
while read e k
do
sed s/$e/$k/g -i kohdefile
done < sanaparitiedosto
Voisi toimiakin ;)
Ja tällaiseen skriptiin olisin valmis tekemään vaikka funktion tuosta sedisilmukasta...
Tässä on idistä.
Todellakin ongelmani on "tekninen", eli pitää korvata "TAGeja" jollain merkkijonolla.
Siis mallilla:
TAGI1=sana
TAGI2=sitä sun tätä
TAGI3=jotain muuta, mutta vain rivinvaihtoon saakka
Eli siis voin itse määrätä (input-tiedostossa) mitä etsitään ja millaiseksi korvataan.
Kyseessä on eräiden useissa hakemistoissa olevien konfiguraatiotiedostojen kustomointi, eli esimerkiksi jos on vaikkapa 100 kpl asiakkaita, joilla "samanlainen systeemi", mutta "oma konffis", niin pitää muuttaa (useampaan) "tiedosto-templateen" esimerkiksi asiakkaan nimi, kotihakemisto ja vaikkapa IP osoite ja domain nimi jne. Tämä toimisi siis mallilla, jossa luetan tiedosto, jonka sisältö on:
{CUSTOMER_NAME}=Yritys Oy
{CUSTOMER_PHYSICAL_ROOT}=/var/www/yritys/
{CUSTOMER_PUBLIC_IP}=000.000.000.000
{CUSTOMER_PUBLIC_DOMAIN}=yritys.com
jne....
Edit: voisihan nuo tagien sisällöt tulla vaikka tietokannastakin...
Hakemistorakenne templateille voi olla vaikkapa:
yritys/
|__etc
| |_tiedosto1.conf
| |_tiedosto2.conf
|__var
|_joku_hakemisto
|_tiedostoX.YYY
Olisi siis tarkoitus saada generoitua nuo valmiiksi tuotantoonsiirtoa varten asiakaskohtaisesti.
-
Jassoo, jaajoo...
Joten arvoparien ensimmäistä osaa ei tarvitse muuttaa, kunhan korjaa sen toisen osan?
Ja tarvittaessa lisää avaimen ellei sitä ole?
Mutta esimerkkisi mukaan tuo kenttäerotin on yhtäsuuruusmerkki ja sillä siisti.
Eli kääntyisin nöyränä poikana awk:n puoleen ja lukaisen muuttujat
while read raw
do
e=$(echo $raw |awk -F'=' '{print $1}')
k=$(echo $raw |awk -F'=' '{print $2}')
echo $e $k
done < parit.lst
-
OK, sori hieman pitkä viive vastaukselle, eli muita duuneja välissä... ;-)
Kun en nyt tunne kovin hyvin tuota awk:ta ja ei ollut aikaa pahemmin tuunata, niin päädyin sitten tähän "ei niin kauniiseen" ratkaisuun. Se toimii osaltani (vaikka onkin ohjelmointiteknisesti hieman typerä).
#!/bin/bash
DPATH="./testi/*"
TFILE="/tmp/frt.tmp.$$"
function _find_replace {
while read raw
do
e=$(echo $raw | awk -F'=' '{print $1}')
k=$(echo $raw | awk -F'=' '{print $2}')
for f in $1
do
if [ -f $1 -a -r $1 ]; then
sed "s/$e/$k/g" "$1" > $TFILE && mv $TFILE "$1"
else
echo "Error: Cannot read file $1"
fi
done
done
}
function _read_file {
for f in $1
do
if [ -d "$1" ]
then
for ff in $1/*
do
_read_file $ff
done
else
_find_replace $1
fi
done < parit.lst
}
_read_file $DPATH
Toisaalta alkuperäinen kysymyshän oikeastaan oli, että löytyykö valmiina, joten jos ei löydy, niin tässä on siis "puolivalmis". Joku voi ehkä tuunata tuohon tiedostontyyppien etsinnän jne... Nythän tuo korvaa annetusta polusta "kaikki filet" ja ne tagit jotka löytyvät tiedostosta "parit.lst".
Edit: tagasin ratkaistuksi.
-
-----
Toisaalta alkuperäinen kysymyshän oikeastaan oli, että löytyykö valmiina, joten jos ei löydy, niin tässä on siis "puolivalmis". Joku voi ehkä tuunata tuohon tiedostontyyppien etsinnän jne... Nythän tuo korvaa annetusta polusta "kaikki filet" ja ne tagit jotka löytyvät tiedostosta "parit.lst".
Edit: tagasin ratkaistuksi.
Alkuverryttelynä voisi käyttää ihan tiedoston nimeen perustuvaa suodatusta.
Kuten jossain vilahti malli, niin tiedostot olivat nimetty tyyliin jotain.conf
Tekisin listan jotenkin vaikka:
echo $(find $alkuhakemisto -name "*conf")
Mutta kuten hyvin tiedät niin tapoja on monia - ja useimmat tekevät sen kun pyydetään :)
Tietysti jos haluaa pelata hiukan varmemman päälle niin ehdollistaa tiedostotyypin mukaan
Toistaiseksi on riittänyt ihan 'file'
~$ file /etc/dhcp/dhcpd.conf
/etc/dhcp/dhcpd.conf: ASCII English text
-
Hei, mites tämä: http://docs.kde.org/stable/en/kdewebdev/kfilereplace/kfilereplace-the-add-dialog.html
Winkun puolella on tullut käytettyä .CSV-tiedostoja ymmärtäviä softia, kuten PowerGREP ja TextCrawler, joten aihe on tuttu.
-
Minulla tuli tarve muuttaa sana kaikkialla määrättävässä tiedostojärjestelmän osassa. Itse käsky on yksinkertainen: find mistä_kansiosta_eteenpäin_muutetaan -type f -exec sed -i "s/mikä/miksi/g" {} \;
- käsky toimi ihan oikein. Toivoin vain myöhemmin etten olisi käyttänyt sitä sillä se muutti järjestelmässäni kaiken minkä halusin ja paljon sellaista mitä en olisi halunnut.
- tajusin sentään ennen käskysuoritusta ottaa backupin joten tuhraantui vain aikaa.
# edellinen käsky muuttaa välittämättä siitä mitä vaihdettavan edessä ja perässä on. Seuraava kolmilauseinen käsky olettaa
että muutettavan sanan edessä ja perässä on välilyönti. Tämä vastaa määritelmää: sana. Koska sana voi myös alkaa tai
lopettaa lauseen täytyy ennen muutoksia jokaisen rivin alkuun ja loppuun lisätä välilyönti ja muutoksien tekemisen jälkeen ne tulee poistaa.
find mistä -type f -exec sed -i 's/^ */\ /g;s/ *$/\ /g' {} \; # tiedostojen rivien eteen ja perään lisätään välilyönti;
find mistä -type f -exec sed -i "s/\ mikä\ /\ miksi\ /g" {} \; # sanojen muutokset tiedostoissa;
find mistä -type f -exec sed -i 's/^\ //g;s/\ $//g' {} \; # tiedostojen rivien alusta ja lopusta poistetaan lisätty välilyönti
- siis etsittävän eteen ja perään ei yritetä liittää välilyöntiä; ne välilyönnit ovat muutettavassa tekstissä.
- tämä epämääräisyys on puhutun kielen ja kielioppien epämääräisyyttä ja koskevat millähyvänsä kielellä tehtyä ohjelmaa ja
myös valmisohjelmia.
- edelliset kolme lausetta voi supistaa yhdeksi, mutta silloin selväpiirteisyys katoaa.
Mutta ei homma tähän lopu. Mahdollisuuksia on noin ziljoona. Pitäisi tehdä ohjelma jossa muutokset tehdään editorissa luvan
jälkeen, se kelpaisi useimmiten.
Ja mikäli muutokset lukee tiedostosta tulee lisää epämääräisyyksiä elikkä automaatti-katastrofeja.