ubuntuusers.de

Funktionen für Script in externer Datei übergeben

Status: Gelöst | Ubuntu-Version: Ubuntu 16.04 (Xenial Xerus)
Antworten |

Sonie

Avatar von Sonie

Anmeldungsdatum:
1. Mai 2012

Beiträge: 133

Wohnort: Höchst im Odenwald

Ich möchte folgendes machen: Bsp.

Suchbegriff="zu suchen"
Ersatz="zu ersetzen"
sed -i /s/$Suchbegriff/$Ersatz/g Zieldatei

da es so viele sind, wollte ich das extern einpflegen

Script-File: Datei_Name,SED_Anweisungen

Datei_name,SED-Anweisung
zu_bearbeitende_datei,s/$Suchbegriff/$Ersatz/g

diese wird eingelesen und soll dann ausgeführt werden.

while read line; do
     this=$(cut -d, -f2 <<< $line)
     sed -i "$(this)" $(cut -d, f1 <<< $line) 
done < $Script-File

ergibt dann als Ergebnis:

sed -i "s/$Suchbegriff/$Ersatz/g" "zu_bearbeitende_datei" 

soll aber geben:

sed -i "s/zu suchen/zu ersetzen/g" "zu_bearbeitende_datei"

wie bekomme ich die Variablen in den Variablen aufgelößt?

ChickenLipsRfun2eat Team-Icon

Anmeldungsdatum:
6. Dezember 2009

Beiträge: 12067

Hallo!

Ob das mit dem Auflösen und übergeben der Variablen so funktioniert, weiß ich auch nicht. Falls die Variableninformation enthalten ist, könntest du sie mit $(echo $Suchbegriff) auflösen lassen.

Meine eigentliche Frage dazu ist: Hast du immer den selben Suchbegriff und die selbe Ersetzung bei vielen Dateien? Da wäre vermutlich ein find /Pfad -type f -name "*.wannachange" -exec sed -i s/foo/bar/g einfacher.

track

Avatar von track

Anmeldungsdatum:
26. Juni 2008

Beiträge: 7174

Wohnort: Wolfen (S-A)

Sonie schrieb:

Ich möchte folgendes machen: Bsp.

Suchbegriff="zu suchen"
Ersatz="zu ersetzen"
sed -i s/$Suchbegriff/$Ersatz/g Zieldatei

...

Was hältst Du davon, sämtliche sed-Befehle in ein entsprechendes Skript auszulagern, und das dann an sed zu verfüttern ?

Das Skript sed_test

1
2
3
4
5
6
#!/bin/sed -f

s/such/find/g
s/bier/wein/g

# usw. beliebige sed-Befehle

liefert:

track@track:~$ cat sed_test.txt
versuch 1
probier 2
tu das nich 3
track@track:~$ sed -i -f sed_test  sed_test.txt
track@track:~$ cat sed_test.txt
verfind 1
prowein 2
tu das nich 3 

Normalerweise könnte man das Skript dank des Shebang auch direkt aufrufen, aber das klappt anscheinend mit der Option -i nicht.

LG,

track

Edit:
... ah - man kann damit sogar eine nackte Änderungsliste verarbeiten, wenn man die fehlenden Befehle mit einem 2. sed in einer Process Substitution ergänzt !

Mit meiner Änderungsliste wird das:

track@track:~$ cat sed_liste                                                 # Dies ist meine Liste:
find/such
wein/bier
tu/mach
track@track:~$ sed 's|^|s/|; s|$|/g|' sed_liste                              # ergänze die Befehle mit 2. sed:
s/find/such/g
s/wein/bier/g
s/tu/mach/g
track@track:~$ sed -f <( sed 's|^|s/|; s|$|/g|' sed_liste )  sed_test.txt    # und verfüttere die Ausgabe an das 1. sed:
versuch 1
probier 2
mach das nich 3 

geht also auch so !

Sonie

(Themenstarter)
Avatar von Sonie

Anmeldungsdatum:
1. Mai 2012

Beiträge: 133

Wohnort: Höchst im Odenwald

Ich habe hier diesen Beitrag gefunden, da wird diese Funktion mir der geschweiften Klammer dargestellt.

1
http://stackoverflow.com/questions/2634590/bash-script-variable-inside-variable

aber funktionieren tut es bei mir nicht... 😢

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#/bin/bash
echo "Test"
# Default for Login to Target
result=( "TestName" "TestIP" "TestServerIP" "TestProtokoll" "TestPort" "TestPath" )
file_convert="/opt/prepare/convert_script"

for ((i=0; i <=5; i++)); do
  echo "$i" 
  echo '${result['"$i"']}='"${result[$i]}"
done

cp /opt/apache/current/conf/appadmin/examples/$target_file /tmp
while read line; do
  if [ "$(cut -d, -f1 <<< $line)" == "$target_file" ]; then
    echo $line
    this=$(cut -d, -f2 <<< ${line})
    echo ${this}
    echo "sed -i $this /tmp/$target_file"
    sed -i "$this" /tmp/$target_file
  fi
done < $file_convert

#cat /tmp/$target_file

track

Avatar von track

Anmeldungsdatum:
26. Juni 2008

Beiträge: 7174

Wohnort: Wolfen (S-A)

Ehrlich gesagt verstehe ich nicht, was Dein Skript überhaupt macht oder machen soll. - das wirbelt da irgendwas mit einem Apache-Webserver herum ...

Und wofür brauchst Du hier eine Variable-aufgerufen-durch-eine-Variable (also eine assoziative Variable) ? - das mach alles nur unnötig kompliziert und im Falle von eval auch unsicher.

Du wolltest doch noch immer die Ersetzungen für sed (oder Vergleichbares) auslagern in eine eigene Datei, richtig ?

Wie das unmittelbar mit sed möglich ist, das hatte ich in meinem vorigen Post schon gezeigt.
Wenn Dir das zu windig ist, und Du lieber nur mit den Mitteln der Shell arbeitest, dann geht das ganz ähnlich:

  1. Du liest eine Zeile aus Deiner Listendatei

  2. Du verfütterst sie an den Ersetzungs-Befehl (egal ob das nun sed ist oder eine Parameter-Expansion)

Wenn Du möchtest, zeige ich Dir auch ein Beispiel nur mit der Shell, mit zwei read-Schleifen und einer P-E-Ersetzung. Damit geht das genauso gut.
Aber im Moment ist mir nicht ganz klar, was Du genau willst.

LG,

track

Sonie

(Themenstarter)
Avatar von Sonie

Anmeldungsdatum:
1. Mai 2012

Beiträge: 133

Wohnort: Höchst im Odenwald

Ich habe mein Problem soweit eingegrenzt, dass ich es jetzt hier so erklären kann:

Nur Variable in Variable wird geparst

1
2
3
4
result=( "TestName" "TestIP" )
res='result[1]'
echo "${res}"
echo "${!res}"

ergibt

result[1]
testIP

Variable mit Text in Variable wird nicht gefunden

1
2
3
4
result=( "TestName" "TestIP" )
res='Text davor result[1] Text danach'
echo "${res}"
echo "${!res}"

ergibt

Text davor result[1] Text danach
(leere Zeile)

rklm Team-Icon

Projektleitung

Anmeldungsdatum:
16. Oktober 2011

Beiträge: 13174

Ich möchte noch anmerken, dass das einzelne Aufrufen von sed mit jeweils nur einer Ersetzung extrem ineffizient ist, insbesondere, da es ja wohl "so viele" Ersetzungspaare sind. Alle Ansätze, die ein sed-Skript erzeugen und das dann an sed verfüttern, sind da zu bevorzugen.

track

Avatar von track

Anmeldungsdatum:
26. Juni 2008

Beiträge: 7174

Wohnort: Wolfen (S-A)

Komisch, bei mir geht es:

track@track:~$ result=( "TestName" "TestIP" )
track@track:~$ res='result[1]'
track@track:~$ echo "${res}"
result[1]
track@track:~$ echo "${!res}"
TestIP 

Könnte es sein, dass Du eine andere Shell als die Bash benutzt ?

track

(ich bin erst heute Abend wieder da, muss erstmal arbeiten ...)

Sonie

(Themenstarter)
Avatar von Sonie

Anmeldungsdatum:
1. Mai 2012

Beiträge: 133

Wohnort: Höchst im Odenwald

rklm schrieb:

Ich möchte noch anmerken, dass das einzelne Aufrufen von sed mit jeweils nur einer Ersetzung extrem ineffizient ist, insbesondere, da es ja wohl "so viele" Ersetzungspaare sind. Alle Ansätze, die ein sed-Skript erzeugen und das dann an sed verfüttern, sind da zu bevorzugen.

möchte ich ja, dumm nur, dass die zu ersetzenden inhalte auch erst zur laufzeit bekannt werden, daher suche ich nach einer Möglichkeit, aus den unbekannten Variablen eine SED-Anweisung zu bauen, die ich dann mittels -f übergebe

Sonie

(Themenstarter)
Avatar von Sonie

Anmeldungsdatum:
1. Mai 2012

Beiträge: 133

Wohnort: Höchst im Odenwald

track schrieb:

Komisch, bei mir geht es:

track@track:~$ result=( "TestName" "TestIP" )
track@track:~$ res='result[1]'
track@track:~$ echo "${res}"
result[1]
track@track:~$ echo "${!res}"
TestIP 

Könnte es sein, dass Du eine andere Shell als die Bash benutzt ?

track

(ich bin erst heute Abend wieder da, muss erstmal arbeiten ...)

sagte ich ja, probier das bitte mit "text vor der zu ersetzenden Variable",

res='Text davor result[1] Text danach'

ist nur eine vermutung... wenn ich es richtig verstehe, gibt es zwei verschiedene typen von Strings; einfaches und doppeltes hochkomma...

res1='test/${result[0]}/g'
res2="test/${result[0]}/g"

res1 wird aufgelöst, res2 nicht, gibt es eine Möglichkeit Strings vom Typ res1 nach Typ res2 umzuwandeln?

rklm Team-Icon

Projektleitung

Anmeldungsdatum:
16. Oktober 2011

Beiträge: 13174

Sonie schrieb:

rklm schrieb:

Ich möchte noch anmerken, dass das einzelne Aufrufen von sed mit jeweils nur einer Ersetzung extrem ineffizient ist, insbesondere, da es ja wohl "so viele" Ersetzungspaare sind. Alle Ansätze, die ein sed-Skript erzeugen und das dann an sed verfüttern, sind da zu bevorzugen.

möchte ich ja, dumm nur, dass die zu ersetzenden inhalte auch erst zur laufzeit bekannt werden,

Deshalb kannst Du doch trotzdem ein Skript für sed erzeugen, anstatt es ständig mit nur einer Ersetzung auszuführen. Wo kommen die Ersetzungspaare denn her?

rklm Team-Icon

Projektleitung

Anmeldungsdatum:
16. Oktober 2011

Beiträge: 13174

Sonie schrieb:

wenn ich es richtig verstehe, gibt es zwei verschiedene typen von Strings; einfaches und doppeltes hochkomma...

Genauer sind das zwei Arten Strings zu erzeugen. Das ist ein Unterschied.

res1='test/${result[0]}/g'
res2="test/${result[0]}/g"

res1 wird aufgelöst, res2 nicht, gibt es eine Möglichkeit Strings vom Typ res1 nach Typ res2 umzuwandeln?

So funktioniert das nicht. Das Quoting bestimmt, welcher String als Ergebnis herauskommt. Da gibt es hinterher nix umzuwandeln, weil es nur einen Typ Zeichenketten gibt.

Hier fehlen noch ganz viele Informationen, habe ich den Eindruck. Z.B.

  • Wo kommen die Eingaben (also die Ersetzungspaare) her?

  • Was genau willst Du ersetzen (Muster oder feste Zeichenketten)?

track

Avatar von track

Anmeldungsdatum:
26. Juni 2008

Beiträge: 7174

Wohnort: Wolfen (S-A)

Sonie schrieb:

... probier das bitte mit "text vor der zu ersetzenden Variable",

res='Text davor result[1] Text danach'

Wieso sollte da auch irgendwas mit der Variablen ${result[1]} heraus kommen ?? - diese Variable kommt doch dort überhaupt nicht vor ! Nirgends.

Du solltest vielleicht doch mal verraten, was Du tatsächlich machen willst, vom Kontext her. Im Moment bist Du nur wild am probieren und wunderst Dich, dass da keine sinnvollen Ergebnisse rauskommen ...

track

Sonie

(Themenstarter)
Avatar von Sonie

Anmeldungsdatum:
1. Mai 2012

Beiträge: 133

Wohnort: Höchst im Odenwald

track schrieb:

Sonie schrieb:

... probier das bitte mit "text vor der zu ersetzenden Variable",

res='Text davor result[1] Text danach'

Wieso sollte da auch irgendwas mit der Variablen ${result[1]} heraus kommen ?? - diese Variable kommt doch dort überhaupt nicht vor ! Nirgends.

Du solltest vielleicht doch mal verraten, was Du tatsächlich machen willst, vom Kontext her. Im Moment bist Du nur wild am probieren und wunderst Dich, dass da keine sinnvollen Ergebnisse rauskommen ...

track

natürlich habe ich eine variable result definiert, diese kommt auch aus einer datei... und wird zeilenweise eingelesen. result=( "hostname" "hostip" "port" "protokoll" "virtip" "anything" ) daraus soll dann je virtuellen pc eine config datei für einen apache erstellt werden.

mea culpa, bin davon ausgegangen, dass dies offensichtlich war.

track

Avatar von track

Anmeldungsdatum:
26. Juni 2008

Beiträge: 7174

Wohnort: Wolfen (S-A)

Sonie schrieb:

natürlich habe ich eine variable result definiert, diese kommt auch aus einer datei... und wird zeilenweise eingelesen. result=( "hostname" "hostip" "port" "protokoll" "virtip" "anything" )

Nee, da irrst Du ! - was Du da machst: Du füllst ein Array mit 6 Worten.

Und an diese einzelnen Array-Felder kommst Du eben auch nur genau mit den entsprechenden Array-Ausdrücken ${result[0]} ... ${result[5]} heran, und nicht mit mit einem nackten Wort, an das Du einen Index [1] anhängst. Du musst die Bash-Syntax schon so nehmen, wie sie ist.

Guck Dir doch einfach an, was Du der Shell als Befehlszeile anbietest:

${Text davor result[1] Text danach}

Wie soll die arme Bash darin jemals die Variable ${result[1]} erkennen ?

track

Antworten |