Quale comando (i) alimenterà un file di testo delimitato da tabulazioni e taglierà ogni riga a 80 caratteri?


8

Ho file di testo su più righe di dati (a volte) delimitati da tabulazioni. Vorrei produrre il file in modo da poterlo dare un'occhiata - quindi mi piacerebbe vedere solo i primi 80 caratteri di ogni riga (ho progettato il file di testo per mettere le cose importanti al primo posto su ogni riga).

Pensavo di poter usare cat per leggere ogni riga del file e inviare ogni riga al comando successivo in una pipe:

cat tabfile | cut -c -80

Ma quello sembrava rotto. Ho provato a fare il monkeying e grep sembrava funzionare, ma poi ho scoperto che no, non è vero (non tutte le righe del file avevano più di 80 caratteri) - sembra che le schede siano contate come singoli caratteri per taglio.

Provai:

cat tabfile | tr \t \040 | cut -c -80

Anche se ciò rovinerebbe un po 'i miei dati, eliminando la leggibilità degli spazi bianchi. Ma non ha funzionato. Né ha fatto:

cat tabfile | tr \011 \040 | cut -c -80

Forse sto usando tr sbagliato? Ho avuto problemi con tr prima, volendo rimuovere più spazi (sembra che la versione di tr a cui ho accesso su questa macchina abbia un'opzione -s per comprimere più personaggi - potrei aver bisogno di giocarci di più)

Sono sicuro che se avessi fatto un casino avrei potuto usare perl, awk o sed o qualcosa per farlo.

Tuttavia, vorrei una soluzione che utilizza i comandi regolari (POSIX?), In modo che sia il più portatile possibile. Se finissi per usare tr, probabilmente alla fine proverei a trasformare le schede in caratteri, magari fare un calcolo, tagliare il calcolo, e poi trasformare quei caratteri in schede per l'output.

Non è necessario che sia una singola riga / inserita direttamente nella riga di comando: uno script va bene.


Ulteriori informazioni sui file di tabulazione:

Uso la scheda per spezzare i campi, perché un giorno potrei voler importare dati in qualche altro programma. Quindi tendo ad avere solo una scheda tra i contenuti. Ma uso anche le schede per allineare le cose con le colonne verticali, per facilitare la leggibilità quando guardo il file di testo semplice. Il che significa che per alcune parti di testo riempio la fine del contenuto con spazi fino a quando non arrivo a dove funzionerà la scheda allineando il campo successivo con quelli sopra e sotto di esso.

DarkTurquoise # 00CED1 Mare, cielo, barche a remi Natura
MediumSpringGreen # 00FA9A Utile per gli alberi Magia  
Lime # 00FF00 Solo per polli primaverili e frutta $

Quindi vuoi 80 caratteri contando la larghezza della scheda? È possibile sostituire le schede con un conteggio appropriato di spazi, quindi utilizzare taglia.
muru,

Annnnnd, come posso espandere facilmente un singolo personaggio con più personaggi? O, ancora più importante, con una quantità variabile di caratteri (a seconda di quanti altri caratteri sono presenti nella riga), poiché utilizzo la scheda per allineare le cose verticalmente con quantità diverse di informazioni prima / dopo ogni scheda. Come ho detto, se volessi imparare perl / awk / sed sono sicuro di poterlo fare, ma mi piacerebbe qualcosa di semplice
user3082

Si potrebbe provare prda coreutils: pr -1 -t -l200 -W80 file. Aumenta / diminuisci la lunghezza della pagina (numero dopo -l) secondo le tue necessità.
don_crissti,

Don, il tuo suggerimento (perché non è una risposta?) Mi dà un bel messaggio di errore. Ma l'uomo dice "file di stampa", quindi esaminandolo.
user3082

Don, fai di questa una risposta e discutiamola lì. Ho qualcosa che assomiglia molto al tuo - principalmente lo stesso formato, principalmente gli stessi flag: -w invece di -W, ecc ...
user3082

Risposte:


9

Penso che tu stia cercando expande / o unexpand. Sembra che tu stia cercando di assicurarti che una \tlarghezza ab contenga 8 caratteri anziché quello singolo. foldlo farà anche, ma avvolgerà il suo input alla riga successiva anziché troncarlo. Penso che tu voglia:

expand < input | cut -c -80

expande unexpandsono specificati entrambi POSIX :

  • L' expandutilità deve scrivere i file o l'input standard nell'output standard con i \tcaratteri ab sostituiti con uno o più caratteri spazio necessari per passare al tab stop successivo. Qualsiasi carattere di backspace deve essere copiato nell'output e ridurre il conteggio della posizione della colonna per i calcoli di tabulazione; il conteggio della posizione della colonna non deve essere decrementato sotto lo zero.

Abbastanza semplice. Quindi, ecco uno sguardo a ciò che fa:

unset c i; set --;                                                             
until [ "$((i+=1))" -gt 10 ]; do set -- "$@" "$i" "$i"; done                      
for c in 'tr \\t \ ' expand;  do eval '                                           
    { printf "%*s\t" "$@"; echo; } | 
      tee /dev/fd/2 |'"$c"'| { 
      tee /dev/fd/3 | wc -c >&2; } 3>&1 |
      tee /dev/fd/2 | cut -c -80'
done

Il untilciclo nella parte superiore ottiene un set di dati come ...

1 1 2 2 3 3 ...

È printfquesto con il %*sflag di padding arg, quindi per ognuno di quelli nel set printfriempirà con tutti gli spazi quanti sono nel numero dell'argomento. A ciascuno si aggiunge un \tcarattere ab.

Tutte le tees sono usate per mostrare gli effetti di ciascun filtro mentre viene applicato.

E gli effetti sono questi:

1        2        3        4        5        6        7        8                9               10
1  2   3    4     5      6       7        8         9         10 
1  2   3    4     5      6       7        8         9         10 
66
1        2        3        4        5        6        7        8                9               10
1        2        3        4        5        6        7        8                9               10 
1        2        3        4        5        6        7        8                
105

Quelle file sono allineate in due set come ...

  1. uscita di printf ...; echo
  2. uscita di tr ...oexpand
  3. uscita di cut
  4. uscita di wc

Le prime quattro righe sono i risultati del trfiltro, in cui ogni \tab viene convertito in un singolo spazio .

E i quattro inferiori sono i risultati della expandcatena.


1
In realtà, non importa (troppo) se \ t viene contato come 8 (5?) O uno, solo che non viene conteggiato come uno e visualizzato come 8.
user3082

+ @ anon3202 - ha perfettamente senso. Capisco cosa intendi - (e la lunghezza della tabulazione è un'opzione cli, comunque) - Non l'ho detto proprio come avrei potuto. Spero che tu riesca a capire il senso - come penso io potresti avere.
Mikeserv,

Non ho seguito del tutto la spiegazione, ma il monkeying con espandi mostra che l'espansione è sicuramente quello che stavo cercando.
user3082

3

Poiché le schede sono più per l'allineamento che per la delimitazione, un modo potrebbe essere quello di utilizzare columne quindi cut:

column -s '\t' -t <some-file | cut -c -80

Sembra che columnnon sia POSIX. Fa parte dei programmi di utilità BSD su Ubuntu, quindi presumo che sia abbastanza multipiattaforma.


In columnquesto modo OP non avrebbe nemmeno bisogno di aggiungere manualmente spazi per allinearlo.
Beni Cherniavsky-Paskin,

1

Il suggerimento di Don nei commenti è stato un buon inizio.

Questo è ciò di cui avevo bisogno per farlo funzionare (principalmente):

pr +1 -1 -t -m -l1000 -w 80 tabfile

L' -mera necessario per rendere l' -weffetto bandiera assumono una singola colonna. La pagina man potrebbe usare qualche riscrittura per indicarlo.

Quando ho provato una soluzione alternativa, ho scoperto che prgenera \tcaratteri, quindi alimentare i risultati per ottenere cutlo stesso problema.

-1 (la bandiera della colonna) dice specificamente nella pagina man:

Questa opzione non deve essere utilizzata con -m.

Tuttavia, senza questa opzione prtronca le linee volenti o nolenti, a una lunghezza molto inferiore a quella specificata.

prinserisce anche uno spazio prima (o dopo?) ogni parola in un campo (cioè ogni posto che ho un singolo spazio, ne ha due dopo l'elaborazione). Se ci sono troppe parole, gli spazi inseriti ignorano la -wrestrizione (creando un avvolgimento). Ma, curiosamente, le "colonne" altrimenti non delimitate da tabulazione (ovvero disposte in spazi bianchi) rimangono allineate.



0

Un'utilità che dovrebbe essere veramente consapevole della larghezza del display è fold: sfortunatamente, non sembra avere un'opzione da scartare invece di avvolgere. Anche se probabilmente è terribilmente inefficiente, potresti comunque fare qualcosa del genere

while read -r line; do fold -w80 <<< "$line" | head -n1; done < file
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.