DOMANDA Bash: Sed e awk per dividere una stringa

Dieguitos94

Utente Attivo
221
8
CPU
intel i7 - 6700
Dissipatore
ARCTIC Freezer 7 Pro Rev. 2
Scheda Madre
Msi H170 Gaming M3
Hard Disk
SSD: Samsung 850evo 250 GB + HDD WD Black 1TB
RAM
Corsair Vengeance 2133 Mhz 2x8
Scheda Video
Gigabyte Nvidia GTX 1060 6GB Windforce
Monitor
HP Pavillon x24w
Alimentatore
EVGA Supernova G3 - 550w
Case
NZXT H440 V2
Periferiche
Keyboard: Razer Blackwidow
Sistema Operativo
Windows 10
Salve a tutti!
Avrei un problema con un esercizio Bash che mi richiede di stampare a video tutti i fornitori di fatture.xml per ogni anno.
Le fatture sono già suddivise in cartelle per ogni anno, quindi l'unica cosa che devo fare è prendere, attraverso dei filtri, il fornitore di ogni fattura.
XML:
<CedentePrestatore>
<DatiAnagrafici>
<IdFiscaleIVA>
<IdPaese>IT</IdPaese>
<IdCodice>01234567890</IdCodice>
</IdFiscaleIVA>
<Anagrafica>
<Denominazione>ALPHA SRL</Denominazione>
</Anagrafica>
<RegimeFiscale>RF19</RegimeFiscale>
</DatiAnagrafici>
<Sede>
<Indirizzo>VIALE ROMA 543</Indirizzo>
<CAP>07100</CAP>
<Comune>SASSARI</Comune>
<Provincia>SS</Provincia>
<Nazione>IT</Nazione>
</Sede>
</CedentePrestatore>
Quello che io devo riuscire a stampare è (ad esempio in questo spezzone di fattura) "ALPHA SRL", e quindi tagliare tutto quello che viene prima e che viene dopo.

Ho provato a fare una cosa del tipo:
Bash:
fornitore=$(cat fattura | grep Denominazione | awk '/<Denominazione>/,/</Denominazione>/')
ma non sembra funzionare minimamente.
Calcolando che esistono altri campi "Denominazione", come faccio per prendere solo il primo e fare in modo di salvare in una variabile il nome del fornitore in questo caso "ALPHA SRL" ?

Grazie mille anticipatamente
 

sp3ctrum

Super Moderatore
Staff Forum
8,361
3,185
CPU
Intel i7 6700k @4500 Mhz
Dissipatore
Scythe Mugen 5 rev.b Push&Pull
Scheda Madre
ASUS Z170 Pro Gaming
Hard Disk
SSD Samsung evo 850 250gb + Toshiba P300 3Tb
RAM
G.Skill 16gb Ripjaws V 3200 CL16
Scheda Video
Zotac Nvidia GTX 1080 Mini
Scheda Audio
Topping DX3 Pro + Focusrite Scarlett 2i2 + Creative XFI HD + Edifier Studio R1280T
Monitor
Acer Predator XB241H 144Hz G-Sync
Alimentatore
FSP Raider 650W 80+ Silver
Case
Thermaltake V200 RGB
Internet
Unitymedia 120Mb
Sistema Operativo
Windows 10
Alt, prima di tutto ti consiglio di cambiare i dati sensibili contenuti in questo codice, ai fini della risoluzione del problema, puoi mettere dati finti/generici, attenzione.
 
  • Mi piace
Reactions: Moffetta88

Dieguitos94

Utente Attivo
221
8
CPU
intel i7 - 6700
Dissipatore
ARCTIC Freezer 7 Pro Rev. 2
Scheda Madre
Msi H170 Gaming M3
Hard Disk
SSD: Samsung 850evo 250 GB + HDD WD Black 1TB
RAM
Corsair Vengeance 2133 Mhz 2x8
Scheda Video
Gigabyte Nvidia GTX 1060 6GB Windforce
Monitor
HP Pavillon x24w
Alimentatore
EVGA Supernova G3 - 550w
Case
NZXT H440 V2
Periferiche
Keyboard: Razer Blackwidow
Sistema Operativo
Windows 10
Alt, prima di tutto ti consiglio di cambiare i dati sensibili contenuti in questo codice, ai fini della risoluzione del problema, puoi mettere dati finti/generici, attenzione.
Il file xml in questione è un sample di fattura accessibile da tutti qui. Non è una reale fattura, tranquillo!
 
  • Mi piace
Reactions: Moffetta88

sp3ctrum

Super Moderatore
Staff Forum
8,361
3,185
CPU
Intel i7 6700k @4500 Mhz
Dissipatore
Scythe Mugen 5 rev.b Push&Pull
Scheda Madre
ASUS Z170 Pro Gaming
Hard Disk
SSD Samsung evo 850 250gb + Toshiba P300 3Tb
RAM
G.Skill 16gb Ripjaws V 3200 CL16
Scheda Video
Zotac Nvidia GTX 1080 Mini
Scheda Audio
Topping DX3 Pro + Focusrite Scarlett 2i2 + Creative XFI HD + Edifier Studio R1280T
Monitor
Acer Predator XB241H 144Hz G-Sync
Alimentatore
FSP Raider 650W 80+ Silver
Case
Thermaltake V200 RGB
Internet
Unitymedia 120Mb
Sistema Operativo
Windows 10
ok perfetto ;)
 
  • Mi piace
Reactions: Moffetta88

nullptr

Nuovo Utente
34
9
Molto realisticamente la soluzione più azzeccata per te è proseguire con una espressione XPath attraverso un tool che maneggi l'XML (esempio, xmllint):
Codice:
~ $ xmllint --xpath '//Denominazione/text()' filename
ALPHA SRL
però se vuoi procedere con qualcosa tipo grep:
Codice:
~ $ grep -oP '(?<=<Denominazione>)(.*?)(?=</Denominazione>)' filename
ALPHA SRL
 
  • Mi piace
Reactions: Dieguitos94

« MoMy »

Utente Attivo
1,351
605
Calcolando che esistono altri campi "Denominazione", come faccio per prendere solo il primo e fare in modo di salvare in una variabile il nome del fornitore in questo caso "ALPHA SRL" ?
Si individua un tag univoco come CedentePrestatore e poi filtri quello che ti serve. Un semplice sed risolve, sed -n '/CedentePrestatore/,/CedentePrestatore/p' nome-file.xml
 
  • Mi piace
Reactions: Dieguitos94

Dieguitos94

Utente Attivo
221
8
CPU
intel i7 - 6700
Dissipatore
ARCTIC Freezer 7 Pro Rev. 2
Scheda Madre
Msi H170 Gaming M3
Hard Disk
SSD: Samsung 850evo 250 GB + HDD WD Black 1TB
RAM
Corsair Vengeance 2133 Mhz 2x8
Scheda Video
Gigabyte Nvidia GTX 1060 6GB Windforce
Monitor
HP Pavillon x24w
Alimentatore
EVGA Supernova G3 - 550w
Case
NZXT H440 V2
Periferiche
Keyboard: Razer Blackwidow
Sistema Operativo
Windows 10
Molto realisticamente la soluzione più azzeccata per te è proseguire con una espressione XPath attraverso un tool che maneggi l'XML (esempio, xmllint):
Codice:
~ $ xmllint --xpath '//Denominazione/text()' filename
ALPHA SRL
però se vuoi procedere con qualcosa tipo grep:
Codice:
~ $ grep -oP '(?<=<Denominazione>)(.*?)(?=</Denominazione>)' filename
ALPHA SRL
Intanto grazie mille per la risposta. Purtroppo penso di poter usare solamente comandi già implemtantati in Bash, quindi la prima opzione la scarterei.
La seconda invece è molto interessante! Potrei chiederti di spiegarmela un attimo? Si presume che poi io debba spiegare cosa ho fatto al professore e, a prescindere da questo, mi piace sapere che cosa sto implementando nel codice!
Ad esempio: cos'è -oP?
Cos'è quel (.*?) ?
Perchè metti prima di denominazione (?=<) ?
Grazie mille ancora!
Si individua un tag univoco come CedentePrestatore e poi filtri quello che ti serve. Un semplice sed risolve, sed -n '/CedentePrestatore/,/CedentePrestatore/p' nome-file.xml
Questo è perfetto! Grazie mille!
 

nullptr

Nuovo Utente
34
9
Intanto grazie mille per la risposta. Purtroppo penso di poter usare solamente comandi già implemtantati in Bash, quindi la prima opzione la scarterei.
La seconda invece è molto interessante! Potrei chiederti di spiegarmela un attimo? Si presume che poi io debba spiegare cosa ho fatto al professore e, a prescindere da questo, mi piace sapere che cosa sto implementando nel codice!
Ad esempio: cos'è -oP?
Cos'è quel (.*?) ?
Perchè metti prima di denominazione (?=<) ?
Grazie mille ancora!


Questo è perfetto! Grazie mille!
Se vuoi capire cosa fanno quei parametri, potrai leggere il manuale lanciando dal terminale un man grep:
-o, --only-matching
Print only the matched (non-empty) parts of a matching line, with each
such part on a separate output line.
-P, --perl-regexp
Interpret PATTERNS as Perl-compatible regular expressions (PCREs). This
option is experimental when combined with the -z (--null-data) option, and
grep -P may warn of unimplemented features.
-P risolve i pattern con delle PCRE (espressioni regolari compatibili con Perl), mentre -o ti riporta solo le espressioni che combaciano.
Per rispondere alle altre tue due domande, devi prima imparare a livello sintattico le espressioni regolari.

Ti ho consigliato grep perchè è più indicato per quello che ti serve, mentre per esempio sed è uno stream editor ed è proprio per filtrare/trasformare un testo, meglio utilizzarlo quando devi sostituire certe stringhe e qui non ti serve.
 
Ultima modifica:
  • Mi piace
Reactions: Dieguitos94

Dieguitos94

Utente Attivo
221
8
CPU
intel i7 - 6700
Dissipatore
ARCTIC Freezer 7 Pro Rev. 2
Scheda Madre
Msi H170 Gaming M3
Hard Disk
SSD: Samsung 850evo 250 GB + HDD WD Black 1TB
RAM
Corsair Vengeance 2133 Mhz 2x8
Scheda Video
Gigabyte Nvidia GTX 1060 6GB Windforce
Monitor
HP Pavillon x24w
Alimentatore
EVGA Supernova G3 - 550w
Case
NZXT H440 V2
Periferiche
Keyboard: Razer Blackwidow
Sistema Operativo
Windows 10
Provo a richiedere qua per non aprire un altro topic in merito.Avrei un altro problema.
Devo prelevare del testo in mezzo a dell'altro testo (sarebbe un allegato criptato che poi devo scriptare con base64)
Mi spiego:
Il testo sarebbe tipo il seguente:
XML:
<DescrizioneAttachment>Allegato PDF fattura</DescrizioneAttachment>
<Attachment>
nc42uf92hf82y384y23432h432
m32rfj832y4523fijkjfkwjewfw
MNFDiuojhf893u4=($£)=Jciejr8023u09
</Attachment>
Ciò che voglio fare quindi è estrarre "
nc42uf92hf82y384y23432h432
m32rfj832y4523fijkjfkwjewfw
MNFDiuojhf893u4=($£)=Jciejr8023u09 "
in una variabile in modo da poter poi usare il base64 per decriptare l'allegato.
Il problema è che facendo qualcosa tipo:
Bash:
cat fattura2019.xml | sed -n '/<Attachment>/,/<\/Attachment>/p'
Mi prende anche i due "Attachment" che ovviamente non servono ai fini della decriptazione.
Consigli? @nullptr @momy
 

nullptr

Nuovo Utente
34
9
Provo a richiedere qua per non aprire un altro topic in merito.Avrei un altro problema.
Devo prelevare del testo in mezzo a dell'altro testo (sarebbe un allegato criptato che poi devo scriptare con base64)
Mi spiego:
Il testo sarebbe tipo il seguente:
XML:
<DescrizioneAttachment>Allegato PDF fattura</DescrizioneAttachment>
<Attachment>
nc42uf92hf82y384y23432h432
m32rfj832y4523fijkjfkwjewfw
MNFDiuojhf893u4=($£)=Jciejr8023u09
</Attachment>
Ciò che voglio fare quindi è estrarre "
nc42uf92hf82y384y23432h432
m32rfj832y4523fijkjfkwjewfw
MNFDiuojhf893u4=($£)=Jciejr8023u09 "
in una variabile in modo da poter poi usare il base64 per decriptare l'allegato.
Il problema è che facendo qualcosa tipo:
Bash:
cat fattura2019.xml | sed -n '/<Attachment>/,/<\/Attachment>/p'
Mi prende anche i due "Attachment" che ovviamente non servono ai fini della decriptazione.
Consigli? @nullptr @momy
Codice:
grep -oPz "(?<=<Attachment>\n)(.|\n)*\n(?=<\/Attachment>)" fattura2019.xml
Così dovrebbe farti il match pure di dati non Base64 all'interno del tag, non complicarti la vita con sed, usa grep perchè qui puoi.
Con Base64 parliamo di codifica/decodifica, non encryption/decryption.
 
  • Mi piace
Reactions: Dieguitos94

Dieguitos94

Utente Attivo
221
8
CPU
intel i7 - 6700
Dissipatore
ARCTIC Freezer 7 Pro Rev. 2
Scheda Madre
Msi H170 Gaming M3
Hard Disk
SSD: Samsung 850evo 250 GB + HDD WD Black 1TB
RAM
Corsair Vengeance 2133 Mhz 2x8
Scheda Video
Gigabyte Nvidia GTX 1060 6GB Windforce
Monitor
HP Pavillon x24w
Alimentatore
EVGA Supernova G3 - 550w
Case
NZXT H440 V2
Periferiche
Keyboard: Razer Blackwidow
Sistema Operativo
Windows 10
Codice:
grep -oPz "(?<=<Attachment>\n)(.|\n)*\n(?=<\/Attachment>)" fattura2019.xml
Così dovrebbe farti il match pure di dati non Base64 all'interno del tag, non complicarti la vita con sed, usa grep perchè qui puoi.
Con Base64 parliamo di codifica/decodifica, non encryption/decryption.
Grazie ancora! Sempre gentilissimo!
Sai anche dirmi se esiste un comando per sapere in quale cartella mi trovo?
Il pwd mi restituisce tutto il path mentre io vorrei solamente la cartella nella quale mi trovo.
Es:
Facendo pwd mi restituisce: Home/Scrivania/Ciccio
Io vorrei un comando che essendo in "Home/Scrivania/Ciccio" mi restituisca solo "Ciccio".
 

« MoMy »

Utente Attivo
1,351
605
Qui si parla di A B C e forse è il caso di applicarsi un pochettino di più. http://tldp.org/LDP/abs/html/index.html
La guida è vecchiotta ma per il tuo livello (che sia per diletto o un compito per la scuola) va più che bene considerando il fatto che la soluzione alla tua penultima richiesta era presente nei post precedenti. :P
 

nullptr

Nuovo Utente
34
9
Grazie ancora! Sempre gentilissimo!
Sai anche dirmi se esiste un comando per sapere in quale cartella mi trovo?
Il pwd mi restituisce tutto il path mentre io vorrei solamente la cartella nella quale mi trovo.
Es:
Facendo pwd mi restituisce: Home/Scrivania/Ciccio
Io vorrei un comando che essendo in "Home/Scrivania/Ciccio" mi restituisca solo "Ciccio".
Dai un'occhiata all'espansione di parametro: nome_dir=${PWD##*/} && printf '%s\n' $nome_dir, questa è la strada più corretta da scegliere. In alternativa puoi utilizzare basename `pwd`.
 
  • Mi piace
Reactions: Dieguitos94

Dieguitos94

Utente Attivo
221
8
CPU
intel i7 - 6700
Dissipatore
ARCTIC Freezer 7 Pro Rev. 2
Scheda Madre
Msi H170 Gaming M3
Hard Disk
SSD: Samsung 850evo 250 GB + HDD WD Black 1TB
RAM
Corsair Vengeance 2133 Mhz 2x8
Scheda Video
Gigabyte Nvidia GTX 1060 6GB Windforce
Monitor
HP Pavillon x24w
Alimentatore
EVGA Supernova G3 - 550w
Case
NZXT H440 V2
Periferiche
Keyboard: Razer Blackwidow
Sistema Operativo
Windows 10
Qui si parla di A B C e forse è il caso di applicarsi un pochettino di più. http://tldp.org/LDP/abs/html/index.html
La guida è vecchiotta ma per il tuo livello (che sia per diletto o un compito per la scuola) va più che bene considerando il fatto che la soluzione alla tua penultima richiesta era presente nei post precedenti. :P
Ti ringrazio ma a dire la verità è una mia scelta non volermi "applicare di più". Si tratta di un esame parziale universitario diviso in qualcosa come 8 parti. La parte di Bash vale il 5% della votazione finale quando altre parti valgono il 50%.
Quindi grazie ancora per la guida ma non penso che la guarderò mai. Ho già scritto 500 stringhe di codice e speso diverse ore con le quali avrei potuto passare altri esami. Voglio solo finire il più in fretta possibile.

Dai un'occhiata all'espansione di parametro: nome_dir=${PWD##*/} && printf '%s\n' $nome_dir, questa è la strada più corretta da scegliere. In alternativa puoi utilizzare basename `pwd`.
Grazie mille davvero! Oggi quando mi metto sul pc che uso per programmare provo! Sempre gentilissimo
 
Ultima modifica:

Entra

oppure Accedi utilizzando

Discussioni Simili

Hot del momento