2015-07-04 13 views
5

Tôi đang học ngôn ngữ và theo dõi thi nói này:đọc từng dòng từ tiêu chuẩn Bash đầu vào

Nó nên đọc một đầu vào (từ đầu vào tiêu chuẩn) tại một thời điểm (mỗi mục là một chuỗi và sau đó kết thúc bằng một dòng mới).

Câu hỏi của tôi là hai:

  1. Làm thế nào để đọc từng dòng từ đầu vào tiêu chuẩn trong Bash? Cho đến bây giờ tôi đã sử dụng "read string" nhưng tôi không nghĩ rằng nó đọc một dòng tại một thời điểm.

  2. Tôi không biết đây có phải là câu hỏi ngu ngốc hay không, nhưng khi đã tạo tập lệnh, làm cách nào tôi có thể cung cấp nhiều dòng hơn cho kịch bản làm đầu vào (đọc từ đầu vào chuẩn của khóa học). Ví dụ: Tôi chèn hai dòng (helloworld). Làm thế nào để cung cấp cho kịch bản bash hai dòng này?

Trả lời

8

1) Làm thế nào để đọc từng dòng từ đầu vào tiêu chuẩn trong Bash? Cho đến bây giờ tôi đã sử dụng "chuỗi đọc" nhưng tôi không nghĩ rằng nó đọc một dòng tại một thời điểm.

Nguyên mẫu cho read là:

read [options] name[s ...] 

read sẽ đọc một line yếu tố đầu vào name name1 name2 ... tách dòng dựa trên nội dung của Internal Dòng Separator (IFS). Giá trị mặc định cho IFS' \t\n' (nghĩa là spacetabnewline). Nếu bạn chỉ cung cấp một biến duy nhất cho read, bạn sẽ đọc toàn bộ dòng vào biến đó (trừ khi bạn đã đặt dấu phân tách mới với tùy chọn -d thành read). Nếu bạn cung cấp nhiều biến (ví dụ: read -r name name1) việc tách từ sẽ xảy ra dựa trên giá trị hiện tại của IFS. Có nghĩa là nếu bạn cung cấp chuỗi hello world tới:

read -r name 

name="hello world". Mặt khác, nếu bạn cung cấp cùng một chuỗi để:

read -r name name1 

name="hello", name1="world". Điều gì sẽ xảy ra nếu bạn có các từ thừa trong dòng nhưng chỉ có 2 biến? Giả sử chuỗi của bạn bây giờ là "hello big wide world", những gì xảy ra với:

read -r name name1 

name="hello", name1="big wide world". Các từ trong string được gán cho biến của bạn theo thứ tự và nếu không có đủ biến để giữ mỗi từ trong chuỗi, biến cuối cùng sẽ chứa tất cả các từ còn lại trong chuỗi chưa được gán trước đó.

Bạn thay đổi cách tách từ xảy ra bằng cách thay đổi IFS. Hãy xem xét kỹ câu trả lời được cung cấp bởi anubhava cho một ví dụ. Bạn được tự do chỉ định bất kỳ ký tự nào bạn muốn các từ được chia nhỏ. (Hữu ích trong việc nói phân tích một tập csv thiết IFS=$',\n' và có những lời chia trên ',' thay vì không gian)

Để đảm bảo bạn đọc toàn bộ một dòng vào một biến, bạn có thể chỉ cung cấp một biến duy nhất để read và thiết lập IFS='$\n' để bảo đảm tách từ chỉ xảy ra trên newline. (Lưu ý: cung cấp sự thay đổi như một phần của while vòng giới hạn IFS thay đổi phạm vi của vòng lặp đó Ví dụ:.

while IFS='$\n' read -r line; do 
    # do whatever with line 
done 

sẽ bảo đảm rằng mỗi dòng trên stdin sẽ được đọc vào line trong khi vẫn giữ bình thường bên trong vòng lặp, bạn có thể thêm mỗi dòng vào một mảng như anubhava hiển thị trong câu trả lời của mình. (để bảo toàn tất cả khoảng trống IFS= được sử dụng)

4

Bạn có thể làm một cái gì đó như thế này:

# array to hold all lines read 
lines=() 

# read all lines in lines array 
while IFS= read -r line; do 
    lines+=("$line") 
done < file 

# read 3 more lines from stdin 
for ((i=0; i<3; i++)); do 
    read -rp "Enter a line: " line 
    lines+=("$line") 
done 
Các vấn đề liên quan