Penjajaran skrip keluaran Bash shell

29

Skrip saya:

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

Apakah mengeluarkan info seperti ini:

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

yang ingin saya bersihkan untuk mendapatkan sesuatu seperti ini:

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
pijaaa
sumber

Jawaban:

45

Gunakan printfuntuk memformat output (ini juga lebih portabel daripadaecho ). Saya juga akan menyimpan nilai nyata dari urutan pelarian warna daripada menyimpannya dalam bentuk yang membutuhkan ekspansi 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"

%-15sadalah spesifikasi format yang melapisi string dengan spasi di sebelah kanan sehingga panjangnya (dalam jumlah karakter dalam zshdan fishdan byte di sebagian besar cangkang / printf lain ) setidaknya 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|

Dengan pemotongan:

$ 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|

Utilitas lain untuk memformat teks dalam kolom termasuk POSIXexpand :

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

(di sini perluas karakter TAB ( \t) dengan tab berhenti setiap 30 kolom)

Atau BSDcolumn atau POSIXpr :

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

(di sini menghasilkan 2 kolom lebar 36-kolom (lihat -wopsi untuk mengubah lebar halaman dari default 72)).

atau BSDrs :

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

(Seperti columntidak akan mulai menghasilkan sampai telah membaca semua input).

Atau GNUcolumns :

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

zshjuga memiliki beberapa flag ekspansi parameter untuk string padding: ${(l:15:)hostname}untuk bantalan kiri dan ${(r:15:)hostname}untuk bantalan kanan (dengan pemotongan). Dalam ekspansi yang cepat (seperti pada prompt atau dalam print -Patau seperti yang diaktifkan dalam ekspansi parameter dengan %flag), itu juga mendukung %F{green}output warna, sehingga Anda dapat melakukan:

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

Atau:

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

Meskipun konten $hostnamekemudian juga akan tunduk pada ekspansi yang cepat, yang akan merupakan kerentanan perintah injeksi jika konten $hostnametidak di bawah kendali Anda (seperti di hostname='%<a[`reboot`]<')

Stéphane Chazelas
sumber
35

Cukup dengan columnperintah:

yourscript.sh | column -t

Hasil:

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
RomanPerekhrest
sumber
Saya minta maaf untuk pertanyaan bodoh, tetapi di mana saya harus meletakkan perintah itu?
pijaaa
@pijaaa, lihat pembaruan saya, pipa dengan output skrip Anda
RomanPerekhrest
10
Perhatikan bahwa column(perintah BSD, juga porting ke Linux dan ditemukan secara default pada beberapa distribusi, jangan bingung dengan GNU columns) perlu membaca seluruh input sebelum dapat mulai mengeluarkan sesuatu karena perlu menghitung lebar kolom berdasarkan pada yang terluas.
Stéphane Chazelas
3

Perbarui skrip Anda untuk memasukkan nomor yang diatur ke \t(tab) tempat Anda ingin menabrak kolom.

Keluarkan sesuatu yang serupa dengan yang berikut ini akan memberi Anda perataan yang diperlukan:

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
djsmiley2k - Kontrak Karya
sumber
3
Layak menambahkan contoh singkat berdasarkan naskah dalam pertanyaan ...
Stephen Kitt
@StephenKitt ty Stephen, saya mencoba mencari cara untuk membuatnya lebih dari satu baris, dan ini sejujurnya tidak terpikir oleh saya!
djsmiley2k - KK
3
Anda akan melihat bahwa dengan tabstop default setiap 8 kolom, printf 'Network %s\t: Online\n' 8.8.8.8 192.168.122.123tidak sejajar dengan benar. Anda dapat mengatasinya dengan menggunakan expanduntuk memperluas tab dengan penghentian tab yang berbeda seperti yang ditunjukkan dalam jawaban saya.
Stéphane Chazelas
Silakan menerima ini sebagai jawabannya, dengan mengklik ikon centang.
djsmiley2k - KK
0

Untuk menampilkan lebih baik daripada @Roman

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

Kemudian tambahkan \tdi setiap baris untuk membaginya menjadi kolom.

Emidomenge
sumber