Làm thế nào để khám phá một dòng mới bằng cách sử dụng một vòng lặp for?


8

Ở những nơi khác nhau trên web tôi đã tìm thấy:

\015 
\012
\x0a - hex
\n
\r

tất cả dưới dạng từ đồng nghĩa cho các dòng mới / trả lại vận chuyển ...

Nhưng trong kịch bản nhỏ này, tôi không thể nhận ra khi tôi bắt gặp một dòng mới - ai đó có thể cho tôi biết tôi nên kiểm tra những gì trong dòng if không?

#!/bin/bash

test="this is a
test"

for a in "$test"; do

        if [[ "$a" == '\012' ]] ; then
                echo "FOUND NEWLINE"
        fi

echo "$a"

done

1
Tôi có một câu hỏi ngốc nghếch. Tại sao bạn cần phải làm điều này? Nếu bạn đọc từng dòng đầu vào cat | while read line; do ...; done, bạn sẽ biết có một giá trị vận chuyển cho mỗi lần lặp. Nếu đầu vào của bạn có thể là các tệp \rmà không có \n, chỉ cần chuyển đổi tệp tr '\r' '\n'trong khi xử lý đầu vào. Nếu bạn chỉ cần biết nếu có nhiều dòng : wc -l.
nicerobot

Chào mừng bạn đến với Stack Exchange. Vui lòng không chỉnh sửa câu hỏi của bạn theo cách này vì nó làm cho câu trả lời hiện tại trở nên vô nghĩa. Vì bạn đã tìm được cách giải quyết vấn đề của mình, bạn có thể đăng nó dưới dạng câu trả lời thay thế.
Gilles 'SO- ngừng trở nên xấu xa'

@nicerobot nếu không có dòng mới, thì wc -lsẽ trả về 0; bạn nên thêm nó như một câu trả lời
Arcege

@lolfrog giải pháp không nên có trong câu hỏi, bạn nên đánh dấu câu trả lời có giải pháp
Arcege 23/12/11

Câu trả lời:


6

Nếu bạn trực tiếp sử dụng các chuỗi trong một forvòng lặp, nó sẽ hoạt động theo từng từ (ở đây trên một từ: toàn bộ nội dung $testkể từ khi nó được trích dẫn), không phải mỗi ký tự. Bạn cần sử dụng một whilevòng lặp readđể phân tích từng chữ cái hoặc để giới thiệu một tham số số sẽ lặp qua chuỗi.

Ngoài ra, khi sử dụng read, bạn cần đảm bảo rằng các dòng mới và khoảng trắng không được hiểu là dấu phân cách và buộc readphải đọc một char mỗi lần.

Đây là phiên bản hoạt động:

#!/bin/bash

test="this is a
test"

printf %s "$test" | while IFS= read -r -N 1 a; do

        if [[ "$a" == $'\n' ]] ; then
                echo "FOUND NEWLINE"
        fi

printf %s "$a"

done

Bạn có thể thay thế $'\n'bằng $'\012'hoặc $'\x0a', vì tất cả chúng đều đại diện cho cùng một mã dòng mới. Nhưng nó không giống như \015hoặc \r- điều này là viết tắt của quay trở lại vận chuyển (trở về đầu dòng). Trên các hệ thống Linux, các dòng mới được trình bày bằng cách sử dụng \n, nhưng trên Windows chẳng hạn, chúng được thể hiện bằng một chuỗi \r\nthay thế. Đó là lý do tại sao nếu bạn có một tệp văn bản từ Windows, bạn cũng có thể phát hiện các dòng mới bằng cách tìm kiếm \r.


Nói tóm lại, nó đang biến chuỗi thoát được trích dẫn như \nbiểu diễn byte của nó, do đó bạn không cần phải đặt các ngắt dòng được trích dẫn trông xấu xí trong câu lệnh kiểm tra của mình.
rozcietrzewiacz

4

Bạn có thể kiểm tra các dòng mới trong một biến rất dễ dàng trong bash với:

[[ $var = *$'\n'* ]]

Tôi thấy nó thuận tiện hơn để sử dụng:

declare -r EOL=$'\n' TAB=$'\t' # at top of script
..
if [[ $var = *$EOL* ]]; then # to test (no field-splitting in [[ )

1

Tôi khuyên bạn nên sử dụng trvà sau đó test:

if [ -n "$(tr -cd '\n\r' < datafile)" ]; then
    echo "NEWLINE FOUND"
fi

Việc tr -cdloại bỏ tất cả mọi thứ ngoại trừ dòng mới / trả lại vận chuyển. Nếu có dòng mới trong tệp, thì sẽ có đầu ra từ đó -nkiểm tra sẽ trả về đúng.


Điều đó sẽ không hoạt động đối với các tệp không chứa \rs vì thay thế lệnh sẽ loại bỏ các ký tự dòng mới ( "$(printf '\n\n\n\n\n')"là chuỗi trống).
Stéphane Chazelas 17/05/2015
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.