DOMANDA Bash: Sed e awk per dividere una stringa

Pubblicità

Dieguitos94

Utente Attivo
Messaggi
368
Reazioni
27
Punteggio
44
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
 
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.
 
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
 
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
 
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!
 
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:
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
 
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.
 
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".
 
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
 
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`.
 
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:
Pubblicità
Pubblicità
Indietro
Top