staging.inyokaproject.org

Abschnitte aus einer Datei auf mehrere Dateien verteilen

Status: Ungelöst | Ubuntu-Version: Kein Ubuntu
Antworten |

fireworker72

Anmeldungsdatum:
11. März 2017

Beiträge: 64

Hallo an alle Ich bin neu hier und hätte eine Frage an die Profis

Ich habe eine Datei mit 3 Abschnitten Anfang accountName Ende Leeerzeile

Die Leerzeilen hab Ich schon mit sed eingefügt

Wie gehe Ich es am besten an wenn Ich die Abschnitte je in eine Datei speichern möchte jetzt nimmt er immer alle 3 Abschnitte

LG Peter

Moderiert von rklm:

Titel aussagekräftiger gemacht

user_unknown

Avatar von user_unknown

Anmeldungsdatum:
10. August 2005

Beiträge: 17630

1
for user in Peter Paul Mary; do sed -n "/$user/,/^$/p" sample.rc  > $user.rc ; done

Testdatenerzeugung:

1
user=(Peter Paul Mary); for n in {1..3}; do echo -e "${user[$n]}\nfoo=$n\nbar=$((240/(n+1)))\nfasel=dingeling\nfoobar=$((3*n+7))\n" ; done > sample.rc

Testdaten:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
cat sample.rc 
Peter
foo=0
bar=120
fasel=dingeling
foobar=7

Paul
foo=1
bar=80
fasel=dingeling
foobar=10

Mary
foo=2
bar=60
fasel=dingeling
foobar=13

rklm Team-Icon

Projektleitung

Anmeldungsdatum:
16. Oktober 2011

Beiträge: 13242

fireworker72 schrieb:

Hallo an alle Ich bin neu hier und hätte eine Frage an die Profis

Herzlich willkommen hier im Forum!

Ich habe eine Datei mit 3 Abschnitten Anfang accountName Ende Leeerzeile

Kannst Du mal Beispieldaten zeigen? Dann müssen wir nicht raten.

Die Leerzeilen hab Ich schon mit sed eingefügt

Warum fügst Du erst noch Leerzeilen ein, wenn Du die Inhalte doch auf mehrere Dateien verteilen willst?

Wie gehe Ich es am besten an wenn Ich die Abschnitte je in eine Datei speichern möchte jetzt nimmt er immer alle 3 Abschnitte

Gibt es irgendwelche Regeln, wie die Dateien benannt werden sollen? Und brauchst Du das als Skript oder ist das eine einmalige Sache? In letzterem Fall kann man das vermutlich mit vim recht einfach machen.

fireworker72

(Themenstarter)

Anmeldungsdatum:
11. März 2017

Beiträge: 64

Danke erstmal für die Infos

die Leerzeilen hab Ich eingefügt um Blöcke zu erhalten dachte das wär dann einfacher 😉 Hintergrund ist: damit möchte Ich die Daten meiner Amzon (Alexa Echo/Dot) Geräte auslesen, ein Raspberry verarbeitet die Daten dann mit meinem Smarthome weiter und steuert die Geräte dann, dafür werden aber diese Werte benötigt.

Ich würde aus jedem Block accountName:xxxxxxx alles was mit device:xxxx anfängt und die serialNumber:xxxxx benötigen, und das pro Block in einer Datei z.B.: device1.txt device2.txt device3.txt (müssen aber nicht so heißen)

inhalt der Datei

accountName:xxxxxxx
appDeviceList:[]
capabilities:[
CHANGE_NAME
EARCONS
SLEEP
UPDATE_WIFI
CUSTOM_ALARM_TONE
AUDIO_PLAYER
REQUIRES_OOBE_FOR_SETUP
PANDORA
TIMERS_AND_ALARMS
TUNE_IN
SET_LOCALE
SALMON
PAIR_REMOTE
FAR_FIELD_WAKE_WORD
PERSISTENT_CONNECTION
POPTART
DREAM_TRAINING
AUDIBLE
SUPPORTS_SOFTWARE_VERSION
SUPPORTS_CONNECTED_HOME_ALL
PAIR_BT_SINK
PAIR_BT_SOURCE]
charging:null
clusterMembers:[]
deviceAccountId:xxxxxxxxxxxxxx
deviceOwnerCustomerId:xxxxxxxx
deviceType:A3Sxxxxxxxxxxxxxxxxx
essid:
language:null
macAddress:
online:true
parentClusters:[]
postalCode:null
registrationId:null
remainingBatteryLevel:null
serialNumber:xxxxxxxxxxx
softwareVersion:571207720]

accountName:yyyyyyy
appDeviceList:[]
capabilities:[
CHANGE_NAME
EARCONS
SLEEP
UPDATE_WIFI
CUSTOM_ALARM_TONE
AUDIO_PLAYER
REQUIRES_OOBE_FOR_SETUP
PANDORA
TIMERS_AND_ALARMS
TUNE_IN
SET_LOCALE
SALMON
PAIR_REMOTE
FAR_FIELD_WAKE_WORD
PERSISTENT_CONNECTION
POPTART
DREAM_TRAINING
AUDIBLE
SUPPORTS_SOFTWARE_VERSION
SUPPORTS_CONNECTED_HOME_ALL
PAIR_BT_SINK
PAIR_BT_SOURCE]
charging:null
clusterMembers:[]
deviceAccountId:yyyyyyy
deviceOwnerCustomerId:yyyyyyy
deviceType:A3Syyyyyyy
essid:
language:null
macAddress:
online:true
parentClusters:[]
postalCode:null
registrationId:null
remainingBatteryLevel:null
serialNumber:yyyyyyy
softwareVersion:571207720]

accountName:zzzzzzzzz
appDeviceList:[]
capabilities:[
CHANGE_NAME
EARCONS
SLEEP
UPDATE_WIFI
CUSTOM_ALARM_TONE
AUDIO_PLAYER
REQUIRES_OOBE_FOR_SETUP
PANDORA
TIMERS_AND_ALARMS
TUNE_IN
SET_LOCALE
SALMON
PAIR_REMOTE
FAR_FIELD_WAKE_WORD
PERSISTENT_CONNECTION
POPTART
DREAM_TRAINING
AUDIBLE
SUPPORTS_SOFTWARE_VERSION
SUPPORTS_CONNECTED_HOME_ALL
PAIR_BT_SINK
PAIR_BT_SOURCE]
charging:null
clusterMembers:[]
deviceAccountId:zzzzzzzzz
deviceOwnerCustomerId:zzzzzzzzz
deviceType:A3Szzzzzzzzzzzzzzz
essid:
language:null
macAddress:
online:true
parentClusters:[]
postalCode:null
registrationId:null
remainingBatteryLevel:null
serialNumber:zzzzzzzzzzz
softwareVersion:571207720]

LG Peter

Bearbeitet von sebix:

Bitte verwende in Zukunft Codeblöcke, um die Übersicht im Forum zu verbessern!

rklm Team-Icon

Projektleitung

Anmeldungsdatum:
16. Oktober 2011

Beiträge: 13242

fireworker72 schrieb:

die Leerzeilen hab Ich eingefügt um Blöcke zu erhalten dachte das wär dann einfacher 😉

Nee, ist es nicht. Du musst ja die Zeilen automatisch erkennen, hinter oder vor denen Du eine Leerzeile einfügst. Die gleiche Erkennung kannst Du auch nutzen um die Aufteilung auf mehrere Dateien zu machen.

Ich würde aus jedem Block accountName:xxxxxxx alles was mit device:xxxx anfängt und die serialNumber:xxxxx benötigen, und das pro Block in einer Datei z.B.: device1.txt device2.txt device3.txt (müssen aber nicht so heißen)

inhalt der Datei

Das ist ein awk-Einzeiler:

1
awk -F: '$1 == "accountName" {out=$2 ".txt"} {print >out}' eingabe-datei

Erläuterung:

  1. "-F:" setzt den Feldtrenner auf ":".

  2. "$1 == "accountName" erfasst alle Zeilen, deren erstes Feld "accountName" enthält.

  3. "{out=$2 ".txt"}" merkt sich den Account-Namen mit angehängtem ".txt" in der Variable "out".

  4. "{print >out}" gibt für jede Zeile den gesamten Inhalt in die Datei aus, die den Namen hat, der in out gespeichert ist.

fireworker72

(Themenstarter)

Anmeldungsdatum:
11. März 2017

Beiträge: 64

Hallo

wenn Ich das eingebe

awk -F: '$1 == "accountName" {out=$2 ".txt"} {print > out}' curl2.txt

bekomme Ich folgende Fehlermeldung

awk: cannot open "" for output (No such file or directory)

das Verzeichniss und die Datei haben Schreib/Leseberechtigungen

Wenn das funktioniert sollte er 3 Dateien anlegen mit dem Namen und Inhalt accountName richtig?

aber wie bekomme Ich aus dem ersten Block dann deciceAccount deviceOwner deviceType und SerialNummber noch in die selbe Datei bzw. die selben Daten aus dem zweiten Block in die zweite Datei?

rklm Team-Icon

Projektleitung

Anmeldungsdatum:
16. Oktober 2011

Beiträge: 13242

fireworker72 schrieb:

bekomme Ich folgende Fehlermeldung

awk: cannot open "" for output (No such file or directory)

Ein möglicher Grund ist die awk-Version. Gibt doch mal ein:

1
2
3
4
$ ls -il $(type -p awk mawk gawk nawk)
262225 lrwxrwxrwx 1 root root     21 Dez  8  2013 /usr/bin/awk -> /etc/alternatives/awk*
271331 -rwxr-xr-x 1 root root 117768 Mär 24  2014 /usr/bin/mawk*
262835 lrwxrwxrwx 1 root root     22 Dez  8  2013 /usr/bin/nawk -> /etc/alternatives/nawk*

Bei mir werkelt da also der mawk. Der andere ist, dass der Inhalt der Datei anders ist als das, was Du präsentiert hast. Du musst schon die echten Eingabedaten liefern.

das Verzeichniss und die Datei haben Schreib/Leseberechtigungen

Hat mit Rechten nix zu tun: es kann einfach keine leeren Dateinamen geben. Das ist von der Fehlermeldung her klar.

Wenn das funktioniert sollte er 3 Dateien anlegen mit dem Namen und Inhalt accountName richtig?

Korrekt.

aber wie bekomme Ich aus dem ersten Block dann deciceAccount deviceOwner deviceType und SerialNummber noch in die selbe Datei bzw. die selben Daten aus dem zweiten Block in die zweite Datei?

Ich verstehe die Frage nicht. Der Einzeiler macht (bei mir) genau das, was Du angefragt hast: die Blöcke werden auf je eine Datei pro "accountName" aufgeteilt.

schusch

Avatar von schusch

Anmeldungsdatum:
2. September 2008

Beiträge: 324

Steht in der 1.Zeile der Datei eine Zeile der Form

accountName:irgendeinName

? Sonst ist out bei der Ausgabe der ersten Zeile ="".

Gibt es eine Zeile der Form

accountName:

? Dann ist out ab dieser Zeile ="".

fireworker72

(Themenstarter)

Anmeldungsdatum:
11. März 2017

Beiträge: 64

Danke meine Herren funktioniert *freu*

es war am Dateianfang noch eine eckige Klammer

so jetzt hab Ich meine 3 Dateien

jetzt müsste ich nur noch alles rauslöschen bis auf

accountName:BlaBlaBla

deviceAccountId:BlaBlaBla

deviceOwnerCustomerId:BlaBlaBla

deviceType:BlaBlaBla

serialNumber:BlaBlaBla

geht das irgendwie auf einmal? oder kann man das im

awk -F: '$1 == "accountName" {out=$2 ".txt"} {print >out}' curl2.txt

Befehl schon irgendwie integrieren damit er die anderen Zeilen erst gar nicht in die Datei schreibt? mit Zeilen zählen geht es nicht, da die Zeilenanzahl nicht immer Ident ist

Danke und LG Peter

rklm Team-Icon

Projektleitung

Anmeldungsdatum:
16. Oktober 2011

Beiträge: 13242

fireworker72 schrieb:

accountName:BlaBlaBla

deviceAccountId:BlaBlaBla

deviceOwnerCustomerId:BlaBlaBla

deviceType:BlaBlaBla

serialNumber:BlaBlaBla

geht das irgendwie auf einmal? oder kann man das im [...] Befehl schon irgendwie integrieren damit er die anderen Zeilen erst gar nicht in die Datei schreibt? mit Zeilen zählen geht es nicht, da die Zeilenanzahl nicht immer Ident ist

Du kommst immer häppchenweise mit neuen Anforderungen. Es wäre hilfreicher, wenn Du das gleich am Anfang klar gemacht hättest. Du musst nur einen entsprechenden Regulären Ausdruck vor den zweiten Block packen, so dass der nur für die Zeilen gilt, die Du geschrieben haben willst.

fireworker72

(Themenstarter)

Anmeldungsdatum:
11. März 2017

Beiträge: 64

Sorry Hab Ich aber eigentlich weiter oben geschrieben

"Ich würde aus jedem Block accountName:xxxxxxx alles was mit device:xxxx anfängt und die serialNumber:xxxxx benötigen, und das pro Block in einer Datei z.B.: device1.txt device2.txt device3.txt (müssen aber nicht so heißen)"

das check i jetzt irgendwie net!?

"Du musst nur einen entsprechenden Regulären Ausdruck vor den zweiten Block packen, so dass der nur für die Zeilen gilt, die Du geschrieben haben willst."

LG

schusch

Avatar von schusch

Anmeldungsdatum:
2. September 2008

Beiträge: 324

1
2
3
4
5
6
7
awk -F: '/^accountName:/ {
  out=$2 ".txt"
  print >out
} 
/^device:/ { print >>out}
/^serialNumber:/ { print >>out}
' <EingabeDatei

Man hilft ja gerne ☺

track

Avatar von track

Anmeldungsdatum:
26. Juni 2008

Beiträge: 7174

Hi Peter,

zuerst auch mal von mir ein herzliches Willkommen hier auf dem Forum !

fireworker72 schrieb:

...   alles rauslöschen bis auf

accountName:BlaBlaBla

deviceAccountId:BlaBlaBla

deviceOwnerCustomerId:BlaBlaBla

deviceType:BlaBlaBla

serialNumber:BlaBlaBla

geht das irgendwie auf einmal? ...

Ich würde es umgekehrt machen: nur die Zeilen drucken, die Du haben willst.
Die Anderen haben auch schon das Stichwort dafür fallen lassen: sowas geht mit Regulären Ausrücken.

Klar kannst Du die entsprechend einbauen: (so ist das bei awk eigentlich sowieso gedacht)

awk -F: '$1 == "accountName" {out=$2 ".txt"; print > out} /^device/ || /^serialNumber:/ {print >> out}'  curl2.txt

Das ist im Prinzip das selbe was schusch auch schon schreibt, nur habe ich es noch ein bisschen zusammengefasst.
Und ich lasse alle Zeilen durchgehen, die mit "device" anfangen. (nach Deinem Beispiel dachte ich, das passt schon)

LG,

track

rklm Team-Icon

Projektleitung

Anmeldungsdatum:
16. Oktober 2011

Beiträge: 13242

track schrieb:

awk -F: '$1 == "accountName" {out=$2 ".txt"; print > out} /^device/ || /^serialNumber:/ {print >> out}'  curl2.txt

Kann man dann auch zusammenfassen und ich würde die Ausgabe nicht duplizieren:

1
awk -F: '$1 == "accountName" {out=$2 ".txt"} /^(device|serialNumber:|accountName:)/ {print >> out}'  curl2.txt

track

Avatar von track

Anmeldungsdatum:
26. Juni 2008

Beiträge: 7174

Nee, die Trennung, dass er die Datei bei der Schlüsselzeile mit dem "accountName" echt neu schreibt, habe ich bewusst so gelassen.
Denn sonst würde er bei jedem neuen Versuch die Daten an die schon vorhandenen Dateien anhängen (und nicht neu beginnen).

Dann hättest Du womöglich am Ende den Datenblock 5x in der Datei stehen ... 😉

LG,

track

Antworten |