Loop melalui tab file yang digambarkan dalam skrip bash


18

Inilah yang saya miliki sejauh ini:

#!/bin/bash
while read line; do
        DB=$(echo $line | cut -f1)
        USER=$(echo $line | cut -f2)
        PASS=$(echo $line | cut -f3)
        echo DB=$DB USER=$USER PASS=$PASS
done < users.txt

Dan contoh file input:

drupal_1    drupal1 tmmjXSWL
drupal_2    drupal2 FHiJSYHM
drupal_3    drupal3 b7bFNj06
drupal_4    drupal4 0AaV62EL

Dan output dari skrip:

DB=drupal_1 drupal1 tmmjXSWL USER=drupal_1 drupal1 tmmjXSWL PASS=drupal_1 drupal1 tmmjXSWL
DB=drupal_2 drupal2 FHiJSYHM USER=drupal_2 drupal2 FHiJSYHM PASS=drupal_2 drupal2 FHiJSYHM
DB=drupal_3 drupal3 b7bFNj06 USER=drupal_3 drupal3 b7bFNj06 PASS=drupal_3 drupal3 b7bFNj06

Untuk beberapa alasan, setiap variabel diatur ke seluruh baris. Ketika saya gunakan echo users.txt | cut -f1pada baris perintah, ia mengembalikan token dengan baik.

Jawaban:


6

Bagaimana dengan ini?

$ awk '{print "DB="$1"\tUSER="$2"\tPASS="$3}' users.txt
DB=drupal_1 USER=drupal1    PASS=tmmjXSWL
DB=drupal_2 USER=drupal2    PASS=FHiJSYHM
DB=drupal_3 USER=drupal3    PASS=b7bFNj06
DB=drupal_4 USER=drupal4    PASS=0AaV62EL

Saya tidak tahu apakah Anda memiliki masalah untuk dipecahkan, atau bertanya-tanya tentang masalah yang lebih teoretis.


Terima kasih, itu berhasil. Saya mencoba menulis skrip untuk membuat 40+ instalasi Drupal di server untuk kelas yang saya ajarkan. Saya memiliki skrip untuk mengatur DB dan file, ini adalah skrip yang akan menggabungkan semuanya. Masalah dengan kode saya adalah $ line mengubah tab menjadi spasi saat diuraikan. $(echo $line | cut -d" " -f1)juga berfungsi.
mortona42

gagal untuk saya jika ada bidang yang berisi spasi
v01pe

21

Masalahnya ada di perintah echo $line. Karena tidak ada tanda kutip di sekitar $line, shell melakukan kata splitting di atasnya, lalu mengartikan setiap kata sebagai pola globbing. Cobalah dengan

a='*.txt foo'
ls $a

Dalam kasus Anda, tab memisahkan kata, yang kemudian menjadi argumen terpisah echo. The echoperintah mencetak argumen dipisahkan oleh spasi. Jadi, pada cutakhirnya, menerima bidang yang dibatasi-ruang alih-alih bidang yang dibatasi-tab.

Selalu beri tanda kutip ganda di sekitar substitusi variabel $foodan substitusi perintah$(foo) (kecuali jika Anda mengerti mengapa Anda harus meninggalkannya dan mengapa tidak apa-apa untuk melakukannya). echo "$line"akan bekerja di sini, tetapi ini adalah cara yang rumit untuk melakukan apa yang Anda usulkan.

Menjaga pendekatan parsing di shell, Anda bisa membuat readperintah mengurai input ke dalam bidang.

while read DB USER PASS; do
  echo "DB=$DB USER=$USER PASS=$PASS"
done <users.txt

readmembagi bidang yang dipisahkan oleh karakter dalam nilai IFSvariabel, yang terdiri dari spasi dan tab (ditambah baris baru, yang tidak dapat muncul di dalam garis) secara default. Untuk membagi hanya pada tab, atur IFSke satu tab terlebih dahulu. Perhatikan bahwa tab depan dan belakang diabaikan dan tab berturut-turut dihitung sebagai satu.

readmemperlakukan \sebagai karakter khusus: garis miring terbalik yang diikuti oleh baris baru diabaikan; \\menjadi backslash tunggal. Jika Anda ingin menghindari perilaku ini, berikan -ropsi.


15
+1. Untuk mengatur IFS ke tab char di bash:IFS=$'\t'
glenn jackman
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.