Lặp lại thông qua tab mô tả tập tin trong tập lệnh bash


18

Đây là những gì tôi có cho đến nay:

#!/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

Và một mẫu của tệp đầu vào:

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

Và đầu ra từ tập lệnh:

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

Vì một số lý do, mỗi biến được đặt thành toàn bộ dòng. Khi tôi sử dụng echo users.txt | cut -f1tại dòng lệnh, nó sẽ trả về mã thông báo tốt.

Câu trả lời:


6

Còn cái này thì sao?

$ 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

Tôi không thể biết nếu bạn có một vấn đề cần giải quyết, hoặc đang tự hỏi về một vấn đề lý thuyết hơn.


Cảm ơn, điều đó làm việc. Tôi đang cố gắng viết một kịch bản để tạo hơn 40 cài đặt Drupal trên máy chủ cho một lớp tôi đang giảng dạy. Tôi có các tập lệnh để thiết lập DB và tập tin, đây là một phần của tập lệnh sẽ kết hợp tất cả lại với nhau. Vấn đề với mã của tôi là dòng $ biến các tab thành khoảng trắng khi được phân tích cú pháp. $(echo $line | cut -d" " -f1)cũng hoạt động.
mortona42

thất bại đối với tôi nếu bất kỳ trường nào chứa khoảng trắng
v01pe

21

Vấn đề là trong lệnh echo $line. Vì không có dấu ngoặc kép xung quanh $line, shell thực hiện phân tách từ trên đó, sau đó diễn giải từng từ dưới dạng mẫu hình cầu. Dùng thử với

a='*.txt foo'
ls $a

Trong trường hợp của bạn, các tab tách các từ, sau đó trở thành các đối số riêng biệt echo. Các echolệnh in đối số của nó được phân cách bởi một dấu cách. Vì vậy, cutcuối cùng nhận được các trường được phân tách bằng không gian thay vì các trường được phân định bằng tab.

Luôn đặt dấu ngoặc kép xung quanh các thay thế thay thế $foovà thay thế lệnh$(foo) (trừ khi bạn hiểu lý do tại sao bạn cần loại bỏ chúng và tại sao bạn nên làm như vậy). echo "$line"sẽ làm việc ở đây, nhưng đó là một cách phức tạp để làm những gì bạn đề xuất.

Giữ cách tiếp cận của bạn để phân tích cú pháp trong trình bao, bạn có thể thực hiện readlệnh phân tích cú pháp đầu vào thành các trường.

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

readchia tách các trường được phân tách bằng các ký tự trong giá trị của IFSbiến, bao gồm khoảng trắng và tab (cộng với một dòng mới, không thể xảy ra bên trong một dòng) theo mặc định. Để chỉ phân chia tại các tab, IFStrước tiên hãy đặt thành một tab. Lưu ý rằng các tab hàng đầu và dấu được bỏ qua và các tab liên tiếp được tính là một.

readcoi \như một ký tự đặc biệt: dấu gạch chéo ngược theo dòng mới được bỏ qua; \\trở thành một dấu gạch chéo ngược Nếu bạn muốn tránh hành vi này, hãy vượt qua -rtùy chọn.


15
+1. Để đặt IFS thành tab char trong bash:IFS=$'\t'
glenn jackman
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.