sed parancs

Fórumok

Sziasztok! szeretnék kicserélni egy fájlban egy sort egy másikra, erre a sed parancsot használom, de valahogy nem jön össze, a következő sorról lenne szó.
'filesdir' => '/var/lib/tine20/files',
és erre szeretném cserélni
'filesdir' => '/home/data/weboffice/files',
a következő parancsot használom
sed -i "s|^\(\'filesdir\' => \).*$|\1 \'/home\/data\/weboffice\/files\',|" /etc/tine20/config.inc.php

mit rontok el, van valakinek ötlete.
előre is köszönöm.

Hozzászólások

mivel |-t használsz delimiterként és "-t az egész kifejezéshez, így sem a '-t, sem a /-t nem kell escapelni:

sed -i "s|^\('filesdir' =>\).*$|\1 '/home/data/weboffice/files',|" /etc/tine20/config.inc.php

Debian 7, bash alatt így kicseréli.

Szerintem elég lenne csak a "/var/lib/tine20/files" stringet cserélni, ha minden más változatlan, de ha már a teljeset akarod:


fifi@silent:~$ cat teszt.txt
'filesdir' => '/var/lib/tine20/files',
fifi@silent:~$ sed -i "s,'filesdir' => '/var/lib/tine20/files','filesdir' => '/home/data/weboffice/files'," teszt.txt
fifi@silent:~$ cat teszt.txt
'filesdir' => '/home/data/weboffice/files',

Bye, Fifi

Ettől függetlenül a fenti, csúnyácska kifejezésnek működnie kellene.

Ezen a ponton pedig rögtön jön, hogy vagy azt sedet rágja a szú, vagy (távolba nézek) egy elnémított stderrű szkriptbe van ágyazva, és így hiába jelzi, hogy változtatná a fájlt, de nincs hozzá joga.

Ehhez nem kell non-standard -r opció. (Ha még nem mondtam volna elégszer, ha már mindenképp, akkor használj helyette -E opciót.)

sed -e "s|^\([ TAB]*'filesdir'[ TAB][ TAB]*=>[ TAB][ TAB]*\).*$|\1 '/home/data/weboffice/files',|"

Én amúgy Ctrl-V-ot gépelek ott, ahol TAB látszik fentebb, de itt az nem annyira olvasható. Amúgy szerintem azzal is lehet gond, hogy elő van írva a keresésben itt-ott legalább egy szóköz, oszt esetleg nincs egy se, szóval rka példájában minden + *-ra cserélendő, az én verziómban meg ninden XX* helyet csak X* kell :-)

Akinek van -i, annak csak lesz -r is ;) A posternek van -i -je.
Értem, hogy nem _kell_ hozzá a kiterjesztett regexp, de talán tisztább-szárazabb érzés arra fókuszálni, hogy mit akarok kifejezni a kifejezéssel, mint arra, hogy mit kell védeni. A példában gyakorlatilag semmit nem kellett védeni.

Ez most nem jött össze :-) Sem a tiedben, sem az enyémben nincs olyan, ahol védenénk bármit - pontosabban mind a kettőben az egész regexp-et védjük a shell elől. De a regexpen belül már nincs takarás, lévén egyik \ sem az. A tiedben van 3 db \s és egy db \1 - ezek egyike sem "takarás", hanem ezek metaszimbólumok, amik jelentenek valamit. Az enyimben meg van 1 db \(, meg egyszer a párja \) és a \1, ugyanúgy metaszimbólumok. Csak az enyimben eggyel kevesebb darab ilyen van (igaz, eggyel többféle), mint a tiedben. :-)

Formálisan igazad van. A _sed_ esetében a \( \) \{ \}... metakarakterek, a regexpnél meg a ( ) { } [ ] ? . stb.
De a tiszta-száraz érzés nekem az alábbi 3. példa, amikor a \(, meg a \. pont azt fejezi ki, hogy a következő karaktert értelmezés nélkül kérném, a (), {}, [] . magában is a regexp értelmes, jelentéssel bíró részét képező metakarakter, netán átemelhető a kifejezés másik értelmezőbe módosítás nélkül.

Ezért nekem a "\(" az 1. példában "védelem", (mert egy másik értelmező a "("-t is megértené. A "." maga metakarakter, ezért védeni kell középen - olyan zagyva, na.
A 3. példában meg kitisztul minden. A "(" metakarakter lesz, ha meg a karaktere kell, megvédem. Itt a gép érti az igényem, míg fentebb nekem kell a sed _sajátos_ dialektusát érteni.

Azaz - ha lehet - a sed tanuljon meg regexp-ül, ne én sed-ül.


#1
echo 'alma (belma . celma) delma' | sed -e 's/.*\((.*\..*)\).*/\1/'
(belma . celma)

echo 'alma (belma . celma) delma' | sed -re 's/.*\((.*\..*)\).*/\1/'
belma . celma

#3
echo 'alma (belma . celma) delma' | sed -re 's/.*(\(.*\..*\)).*/\1/'
(belma . celma)

--
bocs, ha offtopic
bocs, mert szubjektív

Ott bicsaklik meg az érvelésed, hogy úgy tűnik elfelejtkezel egy apróságról. Ezt az én rendszeremben a man 7 re_format doksi írja:

"Regular expressions (“REs”), as defined in IEEE Std 1003.2 (“POSIX.2”), come in two forms: modern REs (roughly those of egrep(1); 1003.2 calls these “extended” REs) and obsolete REs (roughly those of ed(1); 1003.2 “basic” REs). Obsolete REs mostly exist for backward compatibility in some old programs."

No és a helyzet az, hogy a fent említett ed(1) mellett van két igen elterjedten használt, "basic" RE-t használó program a *x-világban: a grep és a sed. A korábbi használattal ellentétben, amikor is volt grep és (nem sokkal későbbtől) egrep, ma szeretik a grep -E formát tanítani és használni az utóbbi helyett (sőt mintha a POSIX is azt javasolná); ezzel szemben a sednek nagyon sokáig nem volt, sőt a POSIX-szerint ma sincs ERE-t használó verziója / opciója. Azaz jócskán vannak olyan vénemberek, akiknek a sed még mindig inkább BRE-t, mint ERE-t használó eszköz, és mivel tovább látnak a Linuxnál :-P, igyekeznek ezt jelezni is.

Aztán lett perl és PCRE. Ezért van olyan aspektus, ahonnan nézve hordozhatóbb - és ezzel kényelmesebb - az extended regexp. Talán ott van a kutya elásva, hogy nekem a regexp, neked meg a sed az eszköz ebben az esetben? Te úgy fogalmazol, hogy minden sed értse. Én úgy, hogy minden általam használt regexp értelmező értse.

Akkor csak cseréld azt, amit változtatni kell a sorban - amiben nincs se tab, se space - és ne a teljes sort:


sed -i "s,/var/lib/tine20/files,/home/data/weboffice/files," teszt.txt

Persze lehetne rá tökéletes regexp-et gyártani, de minek, ha csak egy egyszerű stringet kell cserélni.

Bye, Fifi


'filesdir' => '/var/lib/tine20/files',
és erre szeretném cserélni
'filesdir' => '/home/data/weboffice/files',

Ne bonyolitsd tul:

sed -e '/filesdir/ s,/var/lib/tine20/files,/home/data/weboffice/files,'

Ez szelektiven csak azokban a sorokban csereli le a /var/lib/tine20/files-t /home/data/weboffice/files-re, amelyik sor illeszkedik a /filesdir/ regexre is.

Erdemes atolvasni a "3.2 Selecting lines with sed" reszt itt: https://www.gnu.org/software/sed/manual/sed.html#Addresses

asd