[sed] Alleen de eerste match

Pagina: 1
Acties:

  • DPLuS
  • Registratie: April 2000
  • Niet online
Hoi,

Ik ben een installatiescriptje aan het schrijven voor mijn webapplicatie.
In de php-scriptjes moeten nu de includebestanden aangepast worden aan de invoer van dit installatiescript. Dit wil ik met sed doen.
Ik had eerst:

code:
1
sed -i "3 s@include('Controller.php');@include('$PATH_TO_PHPFILE/Controller.php');@" $FILE


Dit omdat doorgaans de include die aangepast moet worden zich op regel 3 bevindt.

Maar stel dat hij nu eens niet op regel 3 zit?

Wat ik wil is dat sed alleen de eerste occurence van die include substitueert.
Dus dat hij ophoudt met zoeken naar een match als hij de eerste al een keer gevonden en gewijzigd heeft.

Ik heb er nu echt al een tijdje naar gezocht, maar kon het passende commando/switch niet vinden.

[ Voor 7% gewijzigd door DPLuS op 30-05-2006 12:55 ]


  • xzenor
  • Registratie: Maart 2001
  • Laatst online: 14-10-2022

xzenor

Ja doe maar. 1 klontje suiker.

tis een beetje moeilijkk te vinden en te begrijpen, dat ben ik met je eens
Het staat wel in de manpage maar het heeft mij ook moeite gekost..

code:
1
sed 1s/http/ftp/

Dit vervangt de eerste http voor ftp en de rest laat ie met rust.

Ter extra info.
De volgende regel vervangt alleen de 2 http voor ftp en dus niet de eerste 2.
code:
1
sed 2s/http/ftp/


Wil je de eerste 2 http's vervangen dan wordt het dit:
code:
1
sed 1,2s/http/ftp/


Zo...
Korte cursus 'substituting in sed' :)
Nu moet het toch wel lukken denk ik.

[ Voor 7% gewijzigd door xzenor op 24-05-2006 16:39 ]


  • DPLuS
  • Registratie: April 2000
  • Niet online
Volgens mij klopt het niet, en staan die getallen voor s gewoon voor regelnummers.
Dit krijg ik:

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
patrick@testing:~/web$ sed --version
GNU sed version 4.1.5
Copyright (C) 2003 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE,
to the extent permitted by law.
patrick@testing:~/web$ cat blaat 
     1  aap aap aap
     2  noot noot noot
     3  mies mies mies
     4  aap aap aap
     5  aap aap aap
patrick@testing:~/web$ sed 1s/aap/bliep/ blaat   
     1  bliep aap aap
     2  noot noot noot
     3  mies mies mies
     4  aap aap aap
     5  aap aap aap
patrick@testing:~/web$ sed 2s/aap/bliep/ blaat  
     1  aap aap aap
     2  noot noot noot
     3  mies mies mies
     4  aap aap aap
     5  aap aap aap
patrick@testing:~/web$ sed 3s/aap/bliep/ blaat  
     1  aap aap aap
     2  noot noot noot
     3  mies mies mies
     4  aap aap aap
     5  aap aap aap
patrick@testing:~/web$ sed 4s/aap/bliep/ blaat  
     1  aap aap aap
     2  noot noot noot
     3  mies mies mies
     4  bliep aap aap
     5  aap aap aap
patrick@testing:~/web$ sed '4 s/aap/bliep/' blaat 
     1  aap aap aap
     2  noot noot noot
     3  mies mies mies
     4  bliep aap aap
     5  aap aap aap


Krijg jij andere output dan als je bovenstaande test?

  • xzenor
  • Registratie: Maart 2001
  • Laatst online: 14-10-2022

xzenor

Ja doe maar. 1 klontje suiker.

shit.....
ziet er naar uit dat je nog gelijk hebt ook :o
ff uitzoeken

edit:
Vaag, volgens de manpage zou sed s/foo/bar/1 alleen de eerste hit moeten pakken maar dat werkt niet echt.

[ Voor 45% gewijzigd door xzenor op 24-05-2006 17:42 ]


  • DPLuS
  • Registratie: April 2000
  • Niet online
Ja, de eerste hit in één regel.

Dus dit:
code:
1
echo "aap aap aap" | sed s/aap/blaat/1

levert dit als output: blaat aap aap

Als je van die laatste 1 een g (van global) maakt, vervangt 'ie alle occurences op een regel.

[ Voor 5% gewijzigd door DPLuS op 24-05-2006 22:56 . Reden: [code] -> [/code] ]


  • JeroenE
  • Registratie: Januari 2001
  • Niet online
DPLuS schreef op woensdag 24 mei 2006 @ 17:01:
Volgens mij klopt het niet, en staan die getallen voor s gewoon voor regelnummers.
Je kan meer dan alleen getallen gebruiken. In jouw geval kan je waarschijnlijk het beste "0" in combinatie met je regexp gebruiken. In het voorbeeld wat je gaf wordt het dan
code:
1
2
3
4
5
6
sed 0,/aap/s/aap/blaat/ blaat
     1  blaat aap aap
     2  noot noot noot
     3  mies mies mies
     4  aap aap aap
     5  aap aap aap

Verwijderd

Ik gebruik meestal gewoon ed voor zulke klussen.

/include('Controller.php')/
s/include('Controller.php')/include('$PATH_TO_PHPFILE\/Controller.php')/
w
q

Dit zet je in een commando file

cat include.ed | ed file

Het voordeel van ed t.o.v van sed dat hij ook vooruit of achteruit kan.

Bijvoorbeeld.

/blaat/
-1
i
fiets
.
w
q

Altijd handig om ed in je toolbox te hebben.

  • xzenor
  • Registratie: Maart 2001
  • Laatst online: 14-10-2022

xzenor

Ja doe maar. 1 klontje suiker.

DPLuS schreef op woensdag 24 mei 2006 @ 22:56:
Ja, de eerste hit in één regel.

Dus dit:
code:
1
echo "aap aap aap" | sed s/aap/blaat/1

levert dit als output: blaat aap aap

Als je van die laatste 1 een g (van global) maakt, vervangt 'ie alle occurences op een regel.
Ja dat zou je denken als je de manpage leest maar dat werkt dus niet.
Hij vervangt nu alleen de eerste 'occurence' per regel en niet de eerste occurence in het document.
code:
1
2
3
4
5
6
$ printf "aap aap\naap aap\naap aap\naap aap\naap aap" | sed s/aap/blaat/1
blaat aap
blaat aap
blaat aap
blaat aap
blaat aap

  • JeroenE
  • Registratie: Januari 2001
  • Niet online
Ja dat zou je denken als je de manpage leest maar dat werkt dus niet.
Hij vervangt nu alleen de eerste 'occurence' per regel en niet de eerste occurence in het document.
Ik begrijp wellicht niet precies wat je bedoelt, maar sed doet nu precies wat jij zegt dat er moet gebeuren. Je geeft namelijk het commando om op iedere regel "aap" te vervangen door "blaat" en dat voor de eerste occurence te doen; dat laatste is overigens de default en hoef je dus niet per se aan te geven.

Dat is toch precies wat er gebeurt?

Als je wil dat het alleen op de eerste regel gebeurd dan moet je aan het "s" commando meegeven voor welke range de vervanging moet gebeuren. In dit geval volstaat door alleen de 1 mee te geven:
code:
1
2
3
4
5
6
printf "aap aap\naap aap\naap aap\naap aap\naap aap\n" | sed 1s/aap/blaat/
blaat aap
aap aap
aap aap
aap aap
aap aap
De range moet je opgeven voor het commando en niet er na. Dat is wellicht wat je over het hoofd ziet? In jouw voorbeeld is de "1" namelijk onderdeel van het substitute commando.

  • xzenor
  • Registratie: Maart 2001
  • Laatst online: 14-10-2022

xzenor

Ja doe maar. 1 klontje suiker.

Je mist het probleem :)
het is niet duidelijk op welke regel de eerste aap staat, het is alleen duidelijk dat de eerste aap in het bestand door blaat vervangen moet worden.
dus het kan zijn:
aap aap aap
hoi hoi hoi aap
aap hoi aap
aap aap hoi

en dan moet het zo worden:
[b]blaat[/b] aap aap
hoi hoi hoi aap
aap hoi aap
aap aap hoi

Maar dit kan ook het geval zijn
hoi hai hoi
hoi hoi hai
aap hoi aap
hoi aap hoi

En dan zou het zo moeten worden
hoi hai hoi
hoi hoi hai
[b]blaat[/b] hoi aap
hoi aap hoi

Dus er is niet bekend op welke regel het het eerst voor gaat komen.
En ik heb niet het idee dat dit met alleen het sed commando mogelijk is.
Misschien dat ed het inderdaad wel kan zoals al eerder aangegeven werd.

  • xzenor
  • Registratie: Maart 2001
  • Laatst online: 14-10-2022

xzenor

Ja doe maar. 1 klontje suiker.

Nou ik heb heel wat sed pagina's gezien inmiddels...
Ik ben er zelf ook wel nieuwsgierig naar namelijk, maar ik heb het niet kunnen vinden..
Misschien lukt het met ed maar daar weet ik niets van.
Ik zou het met grep oplossen.
code:
1
printf "bla bla hoi\nbla aap hoi\naap bla aap\nbla hoi bla\n" | grep -n -m 1 aap |cut -d : -f 1

Dit geeft een regelnummer waar de eerste 'aap' op staat.Pleur het in een variable en gebruik het in sed om de regel aan te geven die aangepast moet worden...

Zo zou ik het oplossen op mijn eigen systeem..

  • JeroenE
  • Registratie: Januari 2001
  • Niet online
Dus er is niet bekend op welke regel het het eerst voor gaat komen.
En ik heb niet het idee dat dit met alleen het sed commando mogelijk is.
Het kan wel, zoals ik in mijn post van de 26e al had gezegd:
code:
1
sed 0,/aap/s/aap/blaat/ blaat

  • xzenor
  • Registratie: Maart 2001
  • Laatst online: 14-10-2022

xzenor

Ja doe maar. 1 klontje suiker.

code:
1
2
$ printf "bla bla hoi\nbla aap hoi\naap bla aap\nbla hoi bla\n" | sed 0,/aap/s/aap/blaat/ blaat
sed: blaat: No such file or directory

Misschien ligt het aan de versie van sed, maar bij mij werkt het niet...
Mocht die laatste blaat als file bedoeld zijn.. werkt ook niet
code:
1
2
3
4
5
printf "bla bla hoi\nbla aap hoi\naap bla aap\nbla hoi bla\n" | sed 0,/aap/s/aap/blaat/
bla bla hoi
bla aap hoi
aap bla aap
bla hoi bla

  • vanaalten
  • Registratie: September 2002
  • Laatst online: 06-02 16:42
possamai schreef op dinsdag 30 mei 2006 @ 12:30:
Misschien ligt het aan de versie van sed, maar bij mij werkt het niet...
Mocht die laatste blaat als file bedoeld zijn.. werkt ook niet
code:
1
2
3
4
5
printf "bla bla hoi\nbla aap hoi\naap bla aap\nbla hoi bla\n" | sed 0,/aap/s/aap/blaat/
bla bla hoi
bla aap hoi
aap bla aap
bla hoi bla
Ligt waarschijnlijk aan de versie van sed. Heb het geprobeerd op een Red Hat linux systeem, een Debian Sarge linux systeem en een HP-UX11.x UNIX machine. Het werkte goed op het linux systeem, op de HP-UX werkte het niet.

Op de linux machines is het dan ook GNU-sed, op HP-UX is het een gewone originele (?) sed. Ofwel, oplossing voor de TS (als 'ie hier nog meeleest): gebruik GNU-sed en bovenstaande methode.

  • JeroenE
  • Registratie: Januari 2001
  • Niet online
Misschien ligt het aan de versie van sed, maar bij mij werkt het niet...
Dan moet je maar een OS gebruiken waar je echte utilities bij krijgt ipv FreeBSD :+
code:
1
2
3
4
5
6
$sed --version
GNU sed version 4.1.5
Copyright (C) 2003 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE,
to the extent permitted by law.
Dat geeft bij mij dit resultaat
code:
1
2
3
4
5
$printf "bla bla hoi\nbla aap hoi\naap bla aap\nbla hoi bla\n" | sed 0,/aap/s/aap/blaat/
bla bla hoi
bla blaat hoi
aap bla aap
bla hoi bla

Of zelfs:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
H:\>ver

Microsoft Windows [versie 5.2.3790]

H:\>type test.txt
bla bla hoi
bla aap hoi
aap bla aap
bla hoi bla

H:\>sed 0,/aap/s/aap/blaat/ test.txt
bla bla hoi
bla blaat hoi
aap bla aap
bla hoi bla

H:\>

  • DPLuS
  • Registratie: April 2000
  • Niet online
Dit werkt inderdaad:

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
patrick@testing:~/temp$ cat blaat 
    -1  abra cada bra
     0  mies mies mies 
     1  aap aap aap
     2  noot noot noot
     3  mies mies mies
     4  aap aap aap
     5  aap aap aap
patrick@testing:~/temp$ sed 0,/aap/s/aap/blaat/ blaat
    -1  abra cada bra
     0  mies mies mies 
     1  blaat aap aap
     2  noot noot noot
     3  mies mies mies
     4  aap aap aap
     5  aap aap aap


Maar jeroene, wat betekent die 0,/aap nu precies?
Ik interpreteer: de range vanaf regel 0 tot aan de eerste occurence van de regexp?

@VanAalten: Ik draai trouwens Debian Testing, dus dat zit wel snor...

[ Voor 9% gewijzigd door DPLuS op 30-05-2006 13:03 . Reden: Comment @ vanaalten ]


  • xzenor
  • Registratie: Maart 2001
  • Laatst online: 14-10-2022

xzenor

Ja doe maar. 1 klontje suiker.

die 0, moet inderdaad zijn wat jij zegt.. maar mijn sed kent dat dus niet :(
FreeBSD heeft een andere sed blijkbaar... helaas...

  • Zwerver
  • Registratie: Februari 2001
  • Niet online
possamai schreef op dinsdag 30 mei 2006 @ 13:03:
die 0, moet inderdaad zijn wat jij zegt.. maar mijn sed kent dat dus niet :(
FreeBSD heeft een andere sed blijkbaar... helaas...
Check dat eens dan? Ik bedoel ik ben wel nieuwsgierig welke sed jij hebt?

Woonachtig Down Under. Ik negeer je insults niet, maar tegen de tijd dat ik ze lees zijn ze meestal niet relevant meer


  • JeroenE
  • Registratie: Januari 2001
  • Niet online
Maar jeroene, wat betekent die 0,/aap nu precies?
Ik interpreteer: de range vanaf regel 0 tot aan de eerste occurence van de regexp?
Met dien verstande dat regel 0 niet echt bestaat. De eerste regel begint gewoon met adres 1. Je mag als adres dus ook een regexp gebruiken. Dus 3,/jantje/ werkt op regel 3 en verder totdat er een regel komt waarin "jantje" staat. Een opmerking hierbij is dat regel 3 niet wordt getest op het voorkomen van "jantje". Het is echt regel 3 en daarna de volgende regel waar "jantje" in staat.

Als je 0 als eerste adres gebruikt dan is sed al in de "ik zoek naar het tweede adres"-mode en niet in de "wat is mijn eerste adres"-mode. Dat zorgt er dus voor dat er gelijk wordt afgebroken als er een regel voorkomt die aan de regexp voldoet. Dit kan dan ook gelijk de eerste regel zijn.
Ik draai trouwens Debian Testing, dus dat zit wel snor...
Gezien het feit dat de sed uit 2003 is verwacht ik wel dat die manpage hetzelfde is als van mijn unstable systeem. In de manpage staat onder het kopje "Addresses" eea summier utigelegd.

@possamai: uit 5 seconden googlen begreep ik dat je in FreeBSD "gsed" uit de ports collectie kan installeren. Die kan je dan voortaan ook gebruiken voor deze 'geavanceerde' functionaliteit :P

  • xzenor
  • Registratie: Maart 2001
  • Laatst online: 14-10-2022

xzenor

Ja doe maar. 1 klontje suiker.

jeroene schreef op dinsdag 30 mei 2006 @ 17:51:
@possamai: uit 5 seconden googlen begreep ik dat je in FreeBSD "gsed" uit de ports collectie kan installeren. Die kan je dan voortaan ook gebruiken voor deze 'geavanceerde' functionaliteit :P
mja klopt.. staat in de ports.. maar ik wist sowieso al niet welke versie er standaard op stond...Dus ja dan zoekt dat wat lastiger..
Maar blijkbaar is het geen gsed :) anders zou ik'm niet los kunnen installeren :P
Pagina: 1