Allineamento dell'output dello script della shell Bash


29

La mia sceneggiatura:

date
echo -e "${YELLOW}Network check${NC}\n\n"

while read hostname
do

ping -c 1 "$hostname" > /dev/null 2>&1 &&

echo -e "Network $hostname : ${GREEN}Online${NC}" ||
echo -e "${GRAY}Network $hostname${NC} : ${RED}Offline${NC}"

done < list.txt
        sleep 30
clear
done

Fornisce informazioni in questo modo:

Network 10.x.xx.xxx : Online   
Network 10.x.xx.xxx : Offline   
Network 10.x.xx.xxx : Offline   
Network 10.x.xx.xxx : Offline   
Network 10.x.xx.x : Online   
Network 139.xxx.x.x : Online   
Network 208.xx.xxx.xxx : Online   
Network 193.xxx.xxx.x : Online

che vorrei ripulire per ottenere qualcosa del genere:

Network 10.x.xx.xxx       : Online  
Network 10.x.xx.xxx       : Offline   
Network 10.x.xx.xxx       : Offline    
Network 10.x.xx.x         : Online    
Network 139.xxx.x.x       : Online  
Network 208.xx.xxx.xxx    : Online    
Network 193.xxx.xxx.x     : Online  
Network 193.xxx.xxx.xxx   : Offline

Risposte:


45

Utilizzare printfper formattare l'output (è anche più portatile diecho ). Vorrei anche memorizzare il valore reale delle sequenze di escape colore invece di memorizzarle in una forma che richiede l'espansione echo.

RED=$(tput setaf 1) GREEN=$(tput setaf 2) YELLOW=$(tput setaf 3)
NC=$(tput sgr0) 
online="${GREEN}online$NC" offline="${RED}offline$NC"

ping -c 1 "$hostname" > /dev/null 2>&1 && state=$online || state=$offline
printf 'Network %-15s: %s\n' "$hostname" "$state"

%-15sè una specifica di formato che riempie le stringhe di spazi a destra in modo che la lunghezza (in numero di caratteri in zshe fishe byte nella maggior parte delle altre shell / printf ) sia almeno 15.

$ printf '|%-4s|\n' a ab abc abcd abcde
|a   |
|ab  |
|abc |
|abcd|
|abcde|
 printf '|%4s|\n' a ab abc abcd abcde
|   a|
|  ab|
| abc|
|abcd|
|abcde|

Con troncamento:

$ printf '|%.4s|\n' a ab abc abcd abcde
|a|
|ab|
|abc|
|abcd|
|abcd|
$ printf '|%4.4s|\n' a ab abc abcd abcde
|   a|
|  ab|
| abc|
|abcd|
|abcd|
$ printf '|%-4.4s|\n' a ab abc abcd abcde
|a   |
|ab  |
|abc |
|abcd|
|abcd|

Altre utilità per formattare il testo in colonne includono POSIXexpand :

printf 'Network %s\t: %s\n' "$hostname" "$state" | expand -t 30

(qui espandendo il carattere TAB ( \t) con tabulazioni ogni 30 colonne)

O BSDcolumn o POSIXpr :

printf 'Network %s\n: %s\n' "$hostname" "$state" | pr -at2

(qui in uscita su 2 colonne larghe 36 colonne (vedere l' -wopzione per modificare la larghezza della pagina dal valore predefinito di 72)).

o BSDrs :

{
   while...
      printf 'Network %s\n: %s\n' "$hostname" "$state"
   done
} | rs -e 0 2

(come columnnon inizierà a produrre fino a quando non avrà letto tutto l'input).

O GNUcolumns :

printf 'Network %s\n: %s\n' "$hostname" "$state" | columns -w 25 -c 2

zshha anche alcuni flag di espansione dei parametri per il padding delle stringhe: ${(l:15:)hostname}per il padding sinistro e ${(r:15:)hostname}per il padding destro (con troncamento). Nell'espansione dei prompt (come nei prompt o in print -Po come abilitato nelle espansioni dei parametri con il %flag), supporta anche l' %F{green}output a colori, quindi puoi fare:

online='%F{green}online%f'
printf '%s\n' "Network ${(r:15:)hostname}: ${(%)online}"

O:

print -rP "Network ${(r:15:)hostname}: $online"

Anche se il contenuto di $hostnamesarebbe quindi soggetto a una rapida espansione, che costituirebbe una vulnerabilità $hostnameall'inserimento di comandi se il contenuto di non fosse sotto il tuo controllo (come in hostname='%<a[`reboot`]<')


35

Semplicemente con columncomando:

yourscript.sh | column -t

L'output:

Network  10.x.xx.xxx     :  Online
Network  10.x.xx.xxx     :  Offline
Network  10.x.xx.xxx     :  Offline
Network  10.x.xx.xxx     :  Offline
Network  10.x.xx.x       :  Online
Network  139.xxx.x.x     :  Online
Network  208.xx.xxx.xxx  :  Online
Network  193.xxx.xxx.x   :  Online

mi dispiace per la domanda stupida, ma dove dovrei mettere quel comando?
pijaaa,

@pijaaa, vedi il mio aggiornamento, pipe con l'output del tuo script
RomanPerekhrest,

10
Si noti che column(un comando BSD, portato anche su Linux e trovato per impostazione predefinita su alcune distribuzioni, da non confondere con GNU columns) dovrà leggere l'intero input prima che possa iniziare a produrre qualcosa in quanto deve calcolare la larghezza delle colonne in base su quello più largo.
Stéphane Chazelas,

3

Aggiorna lo script per inserire un numero impostato in \t(schede) in cui desideri effettuare il tabout in una colonna.

L'output di qualcosa di simile al seguente ti darebbe l'allineamento richiesto:

Network 10.x.xx.xxx\t: Online   
Network 10.x.xx.xxx\t: Offline   
Network 10.x.xx.xxx\t: Offline   
Network 10.x.xx.xxx\t: Offline   
Network 10.x.xx.x\t: Online   
Network 139.xxx.x.x\t: Online   
Network 208.xx.xxx.xxx\t: Online   
Network 193.xxx.xxx.x\t: Online

3
Varrebbe la pena aggiungere un breve esempio basato sulla sceneggiatura nella domanda ...
Stephen Kitt,

@StephenKitt ty Stephen, stavo cercando di capire come renderlo più di una riga, e questo sinceramente non mi è venuto in mente!
djsmiley2k - CoW

3
Noterai che con i tabstops predefiniti ogni 8 colonne, printf 'Network %s\t: Online\n' 8.8.8.8 192.168.122.123non si allinea correttamente. È possibile aggirare expandil problema utilizzando per espandere le schede con un punto di tabulazione diverso, come mostrato nella mia risposta.
Stéphane Chazelas,

Sentitevi liberi di accettare questa come risposta quindi, facendo clic sull'icona di spunta.
djsmiley2k - CoW

0

Per visualizzare anche meglio di @Roman

yourscript.sh | column -t -s $'\t'

Quindi aggiungere \togni riga per dividerlo in colonna.

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.