Arraywert mit Spezialzeichen "New Line"

Vom einfachen Programm zum fertigen Debian-Paket, Fragen rund um Programmiersprachen, Scripting und Lizenzierung.
Antworten
KingBonecrusher
Beiträge: 375
Registriert: 07.06.2005 09:48:43

Arraywert mit Spezialzeichen "New Line"

Beitrag von KingBonecrusher » 09.07.2007 15:52:03

Ich versuche einem Array ein Wert zuzuweisen, welches ein NEW LINE Zeichen enthält. Die Ausgabe des Array`s hat aber kein NEW LINE mehr drin?!
Gibt es da eine Lösung?

ARRAY=("`lshw -C network | grep -F -A1 -B2 "vendor: "`"); echo $ARRAY

Ausgabe sollte natürlich für $ARRAY so aussehen:

Code: Alles auswählen

vendor: foo
model: foo
foo: foo
Leider bekomme ich sowas raus:

Code: Alles auswählen

vendor: foo model: foo foo: foo
Wo ist denn mein Zeilenumbruch nur geblieben?

gms
Beiträge: 7798
Registriert: 26.11.2004 20:08:38
Lizenz eigener Beiträge: MIT Lizenz

Re: Arraywert mit Spezialzeichen "New Line"

Beitrag von gms » 09.07.2007 20:36:22

KingBonecrusher hat geschrieben:Ausgabe sollte natürlich für $ARRAY so aussehen:

Code: Alles auswählen

vendor: foo
model: foo
foo: foo
unter einem Array stelle ich mir aber so etwas vor:

Code: Alles auswählen

0: wert1
1: wert2
2: wert3
KingBonecrusher hat geschrieben: Leider bekomme ich sowas raus:

Code: Alles auswählen

vendor: foo model: foo foo: foo
genaugenommen bekommst du soetwas raus:

Code: Alles auswählen

gms1 ~ # ARRAY=("`lshw -C network | grep -F -A1 -B2 "vendor: "`");
gms1 ~ # set | grep ARRAY
ARRAY=([0]="       description: Wireless interface
gms1 gms # echo ${ARRAY[0]}
description: Wireless interface product: PRO/Wireless 3945ABG Network Connection vendor: Intel Corporation physical id: 0 -- description: Ethernet interface product: BCM4401-B0 100Base-TX vendor: Broadcom Corporation physical id: 0
also wurde die ganze Wurscht in ARRAY[0] eingetragen

auch nicht sehr viel sinnvoller, aber es sollte verdeutlichen, daß ein Array wahrscheinlich nicht das ist, was du benötigst:

Code: Alles auswählen

gms1 ~ # ARRAY=(`lshw -C network | grep -F -A1 -B2 "vendor: "`);
gms1 ~ # set | grep ARRAY
ARRAY=([0]="description:" [1]="Wireless" [2]="interface" [3]="product:" [4]="PRO/Wireless" [5]="3945ABG" [6]="Network" [7]="Connection" [8]="vendor:" [9]="Intel" [10]="Corporation" [11]="physical" [12]="id:" [13]="0" [14]="--" [15]="description:" [16]="Ethernet" [17]="interface" [18]="product:" [19]="BCM4401-B0" [20]="100Base-TX" [21]="vendor:" [22]="Broadcom" [23]="Corporation" [24]="physical" [25]="id:" [26]="0")
vielleicht noch am ehesten sinnvoll:

Code: Alles auswählen

gms1 gms # IFS=$'\n' ARRAY=(`lshw -C network | grep -F -A1 -B2 "vendor: "`);
gms1 gms # IFS=$'\n' echo "${ARRAY[*]}"
       description: Wireless interface
       product: PRO/Wireless 3945ABG Network Connection
       vendor: Intel Corporation
       physical id: 0
--
       description: Ethernet interface
       product: BCM4401-B0 100Base-TX
       vendor: Broadcom Corporation
       physical id: 0
Gruß
gms

KingBonecrusher
Beiträge: 375
Registriert: 07.06.2005 09:48:43

Beitrag von KingBonecrusher » 10.07.2007 07:10:00

Mit IFS habe ich es vorher gelöst, aber mein Problem ist dann, wenn z.B. der erste Netzwerkadapter zu einer Eigenschaft die ich Abfrage keine Info hat, aber der 2te.

Code: Alles auswählen

       description: Wireless interface
       product: PRO/Wireless 3945ABG Network Connection
       vendor: Intel Corporation
       physical id: 0
-- 
       description: Ethernet interface
       product: BCM4401-B0 100Base-TX
       vendor: Broadcom Corporation
       physical id: 0 
       speed: 100Mb/s
Ich habe bisher mit grep die Werte für vendor, product nacheinander in verschiedene Arrays geschrieben. Nur, würde dann die speed Variable weil nur einmal im 2ten Adapter vorhanden für den ersten Adapter ausgegeben werden bei der Ausgabe. Deswegen wollte ich die Adapter schon vorher trennen.

gms
Beiträge: 7798
Registriert: 26.11.2004 20:08:38
Lizenz eigener Beiträge: MIT Lizenz

Beitrag von gms » 10.07.2007 23:11:32

KingBonecrusher hat geschrieben:Ich habe bisher mit grep die Werte für vendor, product nacheinander in verschiedene Arrays geschrieben.
das ist doch eine gute Lösung
KingBonecrusher hat geschrieben: Nur, würde dann die speed Variable weil nur einmal im 2ten Adapter vorhanden für den ersten Adapter ausgegeben werden bei der Ausgabe.
hier gibt es keinen Automatismus! Das ist ein Bug in deinem Script, der sicherlich auch behoben werden kann.

Ich habe hier zum Beispiel ein kleines Testscript geschrieben:

Code: Alles auswählen

#!/bin/sh

addArray() {
  local key=`echo $1 | sed -e 's|:||g'`
  shift
  local value=${@+"$@"}
  eval $key[$IDX]="$value"
}

TMPFILE=fake.out
# TMPFILE=`mktemp`
# lshw -C network | grep -F -A1 -B2 "vendor: " >$TMPFILE

IDX=0
while read line; do
  if [ "$line" = "--" ]; then
    IDX=$(($IDX+1))
  else
    
    eval addArray $line
  fi
done <$TMPFILE

for ((IDX=0; $IDX<${#vendor[@]}; IDX++)); do
  for key in product vendor description speed ; do
    varname="$key[$IDX]"
    echo "$key[$IDX]     = ${!varname}"
  done
done
nach dem bei mir keine Speed-Wert ausgegeben wird, habe ich zusätzlich deine gepostete Ausgabe von lshw, in eine "fake.out" Textdatei geschrieben und die Variable TMPFILE auf diese Datei gesetzt. Wenn du die auskommentierten Zeilen wieder einkommentierst kannst du das Script mit der echten Ausgabe von lshw testen

Das Script hat bei mir folgende Ausgabe geliefert:

Code: Alles auswählen

gms1 gms # ./x.sh
product[0]     = PRO/Wireless 3945ABG Network Connection
vendor[0]     = Intel Corporation
description[0]     = Wireless interface
speed[0]     =
product[1]     = BCM4401-B0 100Base-TX
vendor[1]     = Broadcom Corporation
description[1]     = Ethernet interface
speed[1]     = 100Mb/s
Gruß
gms

KingBonecrusher
Beiträge: 375
Registriert: 07.06.2005 09:48:43

Beitrag von KingBonecrusher » 11.07.2007 00:56:04

Hallo gms,

erstmal vielen dank für die Hilfe. Habe es mit Deinem Beispiel geschafft, ich suchte nämlich schon immer sowas wie eval :-)

Hast Du kurz Zeit mir shift und local zu erklären? Den Rest verstehe ich. Muss mal sagen dein Script ist wirklich ziemlich professionell, also für mich gesehen!

mfg

Mario

Ps: Mein Code sieht nun so aus (nur für CD-ROM Ausgabe):

http://www.nopaste.org/p/a6wCSvjCeb

Die Fakedatei ist diese:

http://www.nopaste.org/p/asgtzuMAmb

Und die ordentliche Ausgabe:

http://www.nopaste.org/p/aI9TCmAIj

gms
Beiträge: 7798
Registriert: 26.11.2004 20:08:38
Lizenz eigener Beiträge: MIT Lizenz

Beitrag von gms » 11.07.2007 20:23:45

KingBonecrusher hat geschrieben:Hast Du kurz Zeit mir shift und local zu erklären?
mit 'shift n' werden die ersten n Argumente entfernt, das Argument n+1 ist danach das Argument 1:

Code: Alles auswählen

gms1 gms # cat y.sh
#!/bin/sh
testshift() {
  echo vor dem shift:
  echo erstes argument  : $1
  echo weitere argumente: $*
  shift 2
  echo nach dem zweifachen shift:
  echo erstes argument  : $1
  echo weitere argumente: $*
}

testshift arg1 arg2 arg3 arg4
gms1 gms #
gms1 gms #
gms1 gms # ./y.sh
vor dem shift:
erstes argument : arg1
weitere argumente: arg1 arg2 arg3 arg4
nach dem zweifachen shift:
erstes argument : arg3
weitere argumente: arg3 arg4
Normalerweise, wenn eine Variable innerhalb und außerhalb einer Funktion verwendet wird, dann wird diese Variable GEMEINSAM genutzt.
Mit 'local' ändert sich dieses Verhalten, sodaß die Änderung der "lokalen Variable", keinen Einfluß auf eine Variable gleichen Namens, außerhalb dieser Funktion hat.

Code: Alles auswählen

gms1 gms # cat y.sh
#!/bin/sh

test_mit_local() {
  local MY_VARIABLE=XXXX
  echo in der test_mit_local-Funktion ist MY_VARIABLE=$MY_VARIABLE
}

test_ohne_local() {
  MY_VARIABLE=YYYY
  echo in der test_ohne_local-Funktion ist MY_VARIABLE=$MY_VARIABLE
}


MY_VARIABLE=$0
echo in $0 ist MY_VARIABLE=$MY_VARIABLE
test_mit_local
echo in $0 ist MY_VARIABLE=$MY_VARIABLE
test_ohne_local
echo in $0 ist MY_VARIABLE=$MY_VARIABLE
gms1 gms #
gms1 gms #
gms1 gms # ./y.sh
in ./y.sh ist MY_VARIABLE=./y.sh
in der test_mit_local-Funktion ist MY_VARIABLE=XXXX
in ./y.sh ist MY_VARIABLE=./y.sh
in der test_ohne_local-Funktion ist MY_VARIABLE=YYYY
in ./y.sh ist MY_VARIABLE=YYYY
Wenn du öfters Shell-Funktionen schreibst und konsequent alle Hilfsvariablen in diesen Funktionen als 'local' deklarierst, wird dir dies mit einem leichter wartbaren und weniger fehleranfälligem Code belohnt.

Gruß
gms

Antworten