DOMANDA Bash: Sed e awk per dividere una stringa

Dieguitos94

Utente Attivo
268
11
CPU
intel i7 - 6700
Dissipatore
ARCTIC Freezer 7 Pro Rev. 2
Scheda Madre
Msi H170 Gaming M3
HDD
SSD: Samsung 850evo 250 GB + HDD WD Black 1TB
RAM
Corsair Vengeance 2133 Mhz 2x8
GPU
Gigabyte Nvidia GTX 1060 6GB Windforce
Monitor
HP Pavillon x24w
PSU
EVGA Supernova G3 - 550w
Case
NZXT H440 V2
Periferiche
Keyboard: Razer Blackwidow Chroma
OS
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

Amministratore
Staff Forum
15,991
7,844
CPU
AMD Ryzen 5 3900X
Dissipatore
Scythe Mugen 5 rev.b Push&Pull
Scheda Madre
ASUS TUF Gaming B550M-Plus WIFI
HDD
Nvme Samsung EVO 1Tb + SSD Samsung evo 850 250gb + Toshiba P300 3Tb
RAM
HyperX FURY 16gb 3200Mhz
GPU
ASUS Dual GeForce RTX 4070 OC White Edition 12GB GDDR6X
Audio
Topping DX3 Pro + Focusrite Scarlett 2i2 + Mackie MR524 + Beyer DT 770 Pro + Presonus SubWoofer
Monitor
LG Ultragear 27gp850
PSU
Corsair RM850x 80 PLUS Gold
Case
Thermaltake V200 RGB
Net
Vodafone 1000Mb
OS
Windows 11 Pro
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
Reazioni: Moffetta88

Dieguitos94

Utente Attivo
268
11
CPU
intel i7 - 6700
Dissipatore
ARCTIC Freezer 7 Pro Rev. 2
Scheda Madre
Msi H170 Gaming M3
HDD
SSD: Samsung 850evo 250 GB + HDD WD Black 1TB
RAM
Corsair Vengeance 2133 Mhz 2x8
GPU
Gigabyte Nvidia GTX 1060 6GB Windforce
Monitor
HP Pavillon x24w
PSU
EVGA Supernova G3 - 550w
Case
NZXT H440 V2
Periferiche
Keyboard: Razer Blackwidow Chroma
OS
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
Reazioni: Moffetta88

sp3ctrum

Amministratore
Staff Forum
15,991
7,844
CPU
AMD Ryzen 5 3900X
Dissipatore
Scythe Mugen 5 rev.b Push&Pull
Scheda Madre
ASUS TUF Gaming B550M-Plus WIFI
HDD
Nvme Samsung EVO 1Tb + SSD Samsung evo 850 250gb + Toshiba P300 3Tb
RAM
HyperX FURY 16gb 3200Mhz
GPU
ASUS Dual GeForce RTX 4070 OC White Edition 12GB GDDR6X
Audio
Topping DX3 Pro + Focusrite Scarlett 2i2 + Mackie MR524 + Beyer DT 770 Pro + Presonus SubWoofer
Monitor
LG Ultragear 27gp850
PSU
Corsair RM850x 80 PLUS Gold
Case
Thermaltake V200 RGB
Net
Vodafone 1000Mb
OS
Windows 11 Pro
ok perfetto ;)
 
  • Mi piace
Reazioni: 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
Reazioni: Dieguitos94

« MoMy »

Utente Èlite
1,527
768
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
Reazioni: Dieguitos94

Dieguitos94

Utente Attivo
268
11
CPU
intel i7 - 6700
Dissipatore
ARCTIC Freezer 7 Pro Rev. 2
Scheda Madre
Msi H170 Gaming M3
HDD
SSD: Samsung 850evo 250 GB + HDD WD Black 1TB
RAM
Corsair Vengeance 2133 Mhz 2x8
GPU
Gigabyte Nvidia GTX 1060 6GB Windforce
Monitor
HP Pavillon x24w
PSU
EVGA Supernova G3 - 550w
Case
NZXT H440 V2
Periferiche
Keyboard: Razer Blackwidow Chroma
OS
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
Reazioni: Dieguitos94

Dieguitos94

Utente Attivo
268
11
CPU
intel i7 - 6700
Dissipatore
ARCTIC Freezer 7 Pro Rev. 2
Scheda Madre
Msi H170 Gaming M3
HDD
SSD: Samsung 850evo 250 GB + HDD WD Black 1TB
RAM
Corsair Vengeance 2133 Mhz 2x8
GPU
Gigabyte Nvidia GTX 1060 6GB Windforce
Monitor
HP Pavillon x24w
PSU
EVGA Supernova G3 - 550w
Case
NZXT H440 V2
Periferiche
Keyboard: Razer Blackwidow Chroma
OS
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
Reazioni: Dieguitos94

Dieguitos94

Utente Attivo
268
11
CPU
intel i7 - 6700
Dissipatore
ARCTIC Freezer 7 Pro Rev. 2
Scheda Madre
Msi H170 Gaming M3
HDD
SSD: Samsung 850evo 250 GB + HDD WD Black 1TB
RAM
Corsair Vengeance 2133 Mhz 2x8
GPU
Gigabyte Nvidia GTX 1060 6GB Windforce
Monitor
HP Pavillon x24w
PSU
EVGA Supernova G3 - 550w
Case
NZXT H440 V2
Periferiche
Keyboard: Razer Blackwidow Chroma
OS
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 Èlite
1,527
768
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
Reazioni: Dieguitos94

Dieguitos94

Utente Attivo
268
11
CPU
intel i7 - 6700
Dissipatore
ARCTIC Freezer 7 Pro Rev. 2
Scheda Madre
Msi H170 Gaming M3
HDD
SSD: Samsung 850evo 250 GB + HDD WD Black 1TB
RAM
Corsair Vengeance 2133 Mhz 2x8
GPU
Gigabyte Nvidia GTX 1060 6GB Windforce
Monitor
HP Pavillon x24w
PSU
EVGA Supernova G3 - 550w
Case
NZXT H440 V2
Periferiche
Keyboard: Razer Blackwidow Chroma
OS
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
Discord Ufficiale Entra ora!