Toon posts:

[bash] sed: zoek line1 en bewerk line2

Pagina: 1
Acties:
  • 238 views sinds 30-01-2008
  • Reageer

Verwijderd

Topicstarter
Ik zoek een methode om in een bash script een file te doorzoeken op een bepaalde string. Als deze is gevonden, moet de volgende regel in zijn geheel worden vervangen door een nieuwe string. Ik krijg het met bash prima voor elkaar om een bepaalde string in een file te vervangen:
code:
1
sed 's/'$acfPlaceholder'/'$acfNew'/g' $projfile >/tmp/$$ && mv /tmp/$$ $projfile

$projfile is het bestand waar de bewerking betrekking op heeft.

Is het mogelijk om dit te doen met sed?

  • DeMoN
  • Registratie: Maart 2001
  • Laatst online: 06-01 23:13

DeMoN

Pastafari

Beetje vaag dit. Je doet het nu toch ook al met sed?

Wat wil je uiteindelijk bereiken, geef eens meer details over je plan. Misschien zijn er nog andere nuttige tips ook :)

Gamertag: Cosmicv0id
"Het woord Gods is voor mij niets meer dan een expressie en het product van menselijke zwakheid. De Bijbel is een verzamelwerk van legendes die achtenswaardig zijn maar ook primitief en kinderachtig.'' - Albert Einstein


Verwijderd

Topicstarter
Alright sorry voor de onduidelijkheid. Op dit moment vervangt het script een placeholder string in een file met een andere string. Hiervoor plaats ik met de hand de placeholder in de file. Ik wil echter niet met een placeholder werken. Dat zou ook niet hoeven, want de plek van de string die ik wil vervangen is expliciet bekend. De string staat namelijk 1 regel ONDER een voor mij bekende en unieke string. Wat ik dus wil, is dat sed naar deze unieke string zoekt, en dan de regel daaronder vervangt voor mijn nieuwe string.

De file waarin alles moet gebeuren ziet er zo uit:
code:
1
2
3
4
5
6
7
....
EHAM_24_VALKO_1.sid
# data/rts
# data/acf
%THEACFFILE%
# data/wind
050823_DCMS_Firebreaks_EHAM_South_Wind.wind


%THEACFFILE% is op dit moment mijn placeholder, die door mijn huidige script wordt vervangen door een nieuwe string. Echter het kan veel mooier, omdat de string # data/acf uniek is. Ik hoop dat het nu wat duidelijker is.

  • Equator
  • Registratie: April 2001
  • Laatst online: 09-02 07:08

Equator

Crew Council

#whisky #barista

Vervang "# data/acf" door "# data/acf + linebreak + "in te vullen string" + linebreak" :?

  • DeMoN
  • Registratie: Maart 2001
  • Laatst online: 06-01 23:13

DeMoN

Pastafari

CyberJ schreef op dinsdag 01 november 2005 @ 12:05:
Vervang "# data/acf" door "# data/acf + linebreak + "in te vullen string" + linebreak" :?
Dat is wel de simpelste oplossing idd :7

Gamertag: Cosmicv0id
"Het woord Gods is voor mij niets meer dan een expressie en het product van menselijke zwakheid. De Bijbel is een verzamelwerk van legendes die achtenswaardig zijn maar ook primitief en kinderachtig.'' - Albert Einstein


Verwijderd

Topicstarter
Bijna... de regel onder # data/acf bevat een bestandsnaam, wat vanalles kan zijn. Deze bestandsnaam is in principe onbekend dus hier kan sed niet op zoeken. De bestandsnaam eindigt wel altijd op .ACF.

  • Equator
  • Registratie: April 2001
  • Laatst online: 09-02 07:08

Equator

Crew Council

#whisky #barista

Je hoeft er ook niet naar te zoeken.
Je zoekt naar de bekende string, en je vervangt deze in zijn geheel met wederom de bekende string, een crlf je variable bestandnaam en wderom een crlf.

dan staat je variabele bestandsnaam onder je bekende string.

  • DeMoN
  • Registratie: Maart 2001
  • Laatst online: 06-01 23:13

DeMoN

Pastafari

Is het niet zo dat in dat bestandje waar de replace in moet plaatsvinden het te vervangen bestand altijd op line 5 staat?
Zo ja, dan kun je er misschien een andere oplossing voor bedenken. dmv een script elke keer die line vervangen dus.

Met Python bijv. zou ik dit zo even voor je uit kunnen tikken. Ben niet erg sterk in bash :P

code:
1
2
3
4
5
6
7
8
9
10
11
12
#!/usr/bin/env python

source = file('/PAD/NAAR/INTELEZEN/FILE','r').read()

#oude source
print source

sourcelines = source.splitlines()
sourcenew = source.replace(sourcelines[4],"REPLACED")

#nieuwe source
print sourcenew

[ Voor 69% gewijzigd door DeMoN op 01-11-2005 12:59 ]

Gamertag: Cosmicv0id
"Het woord Gods is voor mij niets meer dan een expressie en het product van menselijke zwakheid. De Bijbel is een verzamelwerk van legendes die achtenswaardig zijn maar ook primitief en kinderachtig.'' - Albert Einstein


Verwijderd

Topicstarter
Het regelnummer van de regel die moet worden veranderd is helaas variabel. In onderstaand overzicht zie je een deel van het bestand, met daarin de regel die vervangen moet worden. Van deze regel is:
  • de bovenstaande regel bekend (# data/acf)
  • het regelnummer onbekend
  • de extensie bekend (.ACF)
De meest veilige en robuuste oplossing is m.i. zoeken naar '# data/acf' en dan de regel erna vervangen. Op extensie zoeken zou op zich ook werken maar is wat minder robuust.
code:
1
2
3
4
5
6
7
8
9
10
11
...
EHAM_24_LOPIK_1.sid
EHAM_24_VALKO_1.sid
# data/rts
# data/acf               <<==Deze string is bekend. Regelnummer onbekend.
051004_10_10_12JUL.ACF   <<== Deze string moet vervangen worden maar is onbekend. Regelnummer onbekend. Extensie is WEL bekend!
# data/wind
050823_DCMS_Firebreaks_EHAM_South_Wind.wind

$DCMS Baseline, South Flow. TAAM v2.3. RedHat ent3, upd4.
...

  • Wilke
  • Registratie: December 2000
  • Laatst online: 08:56
Met 'ed' kan het wel, alleen of dat makkelijker is....

Maak een bestand 'script.ed' met de volgende inhoud:

code:
1
2
3
4
5
6
7
/data\/acf
+
d
i
Replacement text
.
w


En laat dat los op je bestand:

cat script.ed | ed mijnbestand.txt

'ed' is alleen niet echt het toppunt van gebruiksvriendelijkheid...maar goed...hier voor de duidelijkheid een versie met comments wat elk commando doet:

code:
1
2
3
4
5
6
7
/data\/acf     # Zoek naar een regel met de tekst data/acf
+                # Ga naar de volgende regel
d                # Wis de huidige regel
i                 # Insert op de huidige plaats alles wat hieronder volgt, tot je de regel '.' tegenkomt
Replacement text
.                 # Einde insertion
w                # schrijf weg (naar zelfde bestand; je kunt ook doen 'w nieuwenaam.txt' ofzo)

  • DeMoN
  • Registratie: Maart 2001
  • Laatst online: 06-01 23:13

DeMoN

Pastafari

Wilke schreef op dinsdag 01 november 2005 @ 13:33:
Met 'ed' kan het wel, alleen of dat makkelijker is....

Maak een bestand 'script.ed' met de volgende inhoud:

code:
1
2
3
4
5
6
7
/data\/acf
+
d
i
Replacement text
.
w


En laat dat los op je bestand:

cat script.ed | ed mijnbestand.txt

'ed' is alleen niet echt het toppunt van gebruiksvriendelijkheid...maar goed...hier voor de duidelijkheid een versie met comments wat elk commando doet:

code:
1
2
3
4
5
6
7
/data\/acf     # Zoek naar een regel met de tekst data/acf
+                # Ga naar de volgende regel
d                # Wis de huidige regel
i                 # Insert op de huidige plaats alles wat hieronder volgt, tot je de regel '.' tegenkomt
Replacement text
.                 # Einde insertion
w                # schrijf weg (naar zelfde bestand; je kunt ook doen 'w nieuwenaam.txt' ofzo)
Hehe ed.. blijft toch mooi :D

En alsnog op extensie (python weer):

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#!/usr/bin/env python

bestand = '/PAD/NAAR/DE/FILE' #in te lezen file
source = file(bestand,'r').read()

# oude source
print source

sourcelines = source.splitlines() # split de source op in lines
a = 0
for line in sourcelines: 
    if line[-4:] == ".ACF":
        print "\nMatch op lijn:",a,"\n"
        linematch = a
    a += 1

# nu die line vervangen met iets anders
newsource = source.replace(sourcelines[linematch],"REPLACED")

# nieuwe source
print newsource


Dit schrijft alleen nog niks weg, het vind, replaced en print het op het scherm.

Maar ik denk dat de TS er nu alsnog wel is toch? :)

Gamertag: Cosmicv0id
"Het woord Gods is voor mij niets meer dan een expressie en het product van menselijke zwakheid. De Bijbel is een verzamelwerk van legendes die achtenswaardig zijn maar ook primitief en kinderachtig.'' - Albert Einstein


  • JeroenE
  • Registratie: Januari 2001
  • Niet online
Wilke schreef op dinsdag 01 november 2005 @ 13:33:
Met 'ed' kan het wel, alleen of dat makkelijker is....
Met sed kan het ook:
code:
1
sed "\:^# data/acf$: {N;s:.*:# data/acf\n$acfNew:}" $projfile
Uitleg:
\:^# data/acf$: zoek de regel die alleen bestaat uit # data/acf
{ begin commando reeks
N voeg de volgende regel aan de patternspace toe (inclusief een newline)
s:.*:# data/acf\n$acfNEW: vervang alles in de patternspace door # data/acf + newline + variable $acfNew
} eindig commando reeks

  • Wilke
  • Registratie: December 2000
  • Laatst online: 08:56
Ed is the standard text editor!!!

Maar even serieus, ed is best wel eng, python is een stuk leesbaarder, en dus is het veel makkelijker om er later nog eens iets aan te veranderen. Een klein nadeel is wel dat python geinstalleerd moet zijn, wat niet overal het geval is. Maar als je hier van uit kunt gaan zou ik toch voor zoiets gaan in plaats van perl, ranzige bash-scripts met een hoop sed/ed/awk/cut-werk.

jeroene: OMG, die is een stuk beter ja...maar zeg nou zelf, als je zoiets zelf morgen nog een keer doorleest, snap je dan meteen wat het doet?

Je kunt echter niet ontkennen dat het voor 1 regel code een heleboel doet :D

[ Voor 30% gewijzigd door Wilke op 01-11-2005 14:20 ]


Verwijderd

Topicstarter
Hehe heren, wat een fantastische oplossingen. Jeroene loopt vandaag weg met het goud _/-\o_ , dit is precies wat ik zoek. Ik heb geen probleem met bash, ten eerste draait het script al prima in bash, en ten tweede omdat ik dit soort 1-regelige oplossingen veel te geil vind (aangestoken door een paar dagen perl-scripten) :9 . Op dit moment staat me linuxbak hard te stampen op de simulaties die ik aan het draaien ben, zodra deze klaar zijn ga ik 'm proberen. Thx!

  • JeroenE
  • Registratie: Januari 2001
  • Niet online
jeroene: OMG, die is een stuk beter ja...maar zeg nou zelf, als je zoiets zelf morgen nog een keer doorleest, snap je dan meteen wat het doet?
Nee, maar dat zou ik van het ed script ook niet weten (want ed gebruik ik nooit).

Gelukkig is iedereen vrij om commentaar toe te voegen aan het script zodat toekomstige generaties weten wat er wordt bedoeld ;)

Verwijderd

Topicstarter
Script werkt perfect, nogmaals thx!
Pagina: 1