Làm cách nào để kiểm tra xem một biến có nhiều dòng không trống trong bash không?


10

Nói rằng tôi có hai biến trong bash:

MULTILINE="I have
more than one line"
SINGLE_LINE="I only have one line
"

Tôi muốn phát hiện khi một biến thực sự chứa nhiều hơn một dòng văn bản, bỏ qua các ký tự dòng mới.

Vậy đây:

if [ some test on "$MULTILINE" ]; then echo 'yes'; else echo 'no'; fi

sẽ in yes, và điều này:

if [ some test on "$SINGLE_LINE" ]; then echo 'yes'; else echo 'no'; fi

sẽ in no.

Đối với trường hợp cụ thể của tôi, tôi không nghĩ rằng tôi cần phải lo lắng về việc dẫn các dòng trống, nhưng sẽ không đau khi biết cách làm điều đó.

Tôi có thể làm cái này như thế nào?



@krowe Cảm ơn bạn, nhưng bạn có thể chỉ ra một câu trả lời cụ thể ở đó mà bỏ qua các dòng trống không? Tôi đã không nhìn thấy bất kỳ. (Cũng chỉnh sửa tiêu đề cho phù hợp.)
jpmc26

Câu trả lời:


5

Giải pháp đơn giản nhất mà tôi biết là:

if (( $(grep -c . <<<"$MULTILINE") > 1 ))

ví dụ:

VAR="a
b"
if (( $(grep -c . <<<"$VAR") > 1 )); then
  echo VAR has more than one line
else
  echo VAR has at most one line
fi

==>

VAR has more than one line

Ở trên bỏ qua tất cả các dòng trống: hàng đầu, dấu và nội thất. Nhưng lưu ý rằng không thể có một dòng trống bên trong trừ khi có ít nhất hai dòng không trống, vì vậy sự tồn tại của nó không thể thay đổi câu hỏi liệu có nhiều hơn một dòng sau khi cắt các dòng trống hàng đầu và dấu.


5
$ echo "$ ĐA NĂNG" | wc -l
2

$ echo "$ SINGLE_LINE" | wc -l
2

$ echo "$ SINGLE_LINE" | sed -re '/ ^ $ / d' | wc -l
1

$ echo "$ ĐA NĂNG" | sed -re '/ ^ $ / d' | wc -l
2

Xem /programming/16414410/delete-empty-lines-USE-sed
để biết thêm về cách cắt / xóa khoảng trắng và dòng trống bằng sed.

Bây giờ để viết if expression ...sử dụng của bạn $( ... )bên trong dấu ngoặc kép để có được số lượng dòng và kiểm tra số lượng:

if ["$ (echo" $ MULTILINE "| sed -re '/ ^ $ / d' | wc -l)" -gt 1]; sau đó
  tiếng vang 'nhiều hơn một dòng'; 
khác 
  tiếng vang 'đơn hoặc không có dòng'; 
fi

0

Một sửa đổi nhỏ cho mã này nên làm điều đó. Bạn có thể đặt nó trong tập lệnh riêng để sử dụng lại như thế này:

#!/bin/bash
nlhit=""
for (( i=0; i<${#1}; i++ )); do
    if [[ "${1:$i:1}" == $'\n' ]]; then
        nlhit="1"
    elif [[ "$nlhit" == "1" ]]; then
        exit 1
    fi
done

exit 0

Sau đó, bạn có thể sử dụng nó như vậy (giả sử rằng bạn đã đặt tên cho tập lệnh trước đó multiline-check.sh):

#!/bin/bash

EMPTYLINE=""
BLANKLINE="    "
ONLYLINES="


"

MULTILINE="I have
more than one line"
SINGLE_LINE="I only have one line
"
SECOND_LINE="
I begin with a newline"


echo -n "EMPTYLINE Check: "
multiline-check.sh "$EMPTYLINE"
if [ $? -eq 1 ]; then echo "Yes"; else echo "No"; fi

echo -n "BLANKLINE Check: "
multiline-check.sh "$BLANKLINE"
if [ $? -eq 1 ]; then echo "Yes"; else echo "No"; fi

echo -n "ONLYLINES Check: "
multiline-check.sh "$ONLYLINES"
if [ $? -eq 1 ]; then echo "Yes"; else echo "No"; fi

echo -n "MULTILINE Check: "
multiline-check.sh "$MULTILINE"
if [ $? -eq 1 ]; then echo "Yes"; else echo "No"; fi

echo -n "SINGLE_LINE Check: "
multiline-check.sh "$SINGLE_LINE"
if [ $? -eq 1 ]; then echo "Yes"; else echo "No"; fi

echo -n "SECOND_LINE Check: "
multiline-check.sh "$SECOND_LINE"
if [ $? -eq 1 ]; then echo "Yes"; else echo "No"; fi

Tôi đang nhận được một lỗi cú pháp đầu tiên fi. Thật không may, tôi bị kẹt trên bash 3.1 (phiên bản msysgit). Tôi không thấy bất cứ điều gì trông giống như lỗi cú pháp đối với tôi, nhưng rõ ràng là tôi đang thiếu một cái gì đó. Suy nghĩ?
jpmc26

@ jpmc26 Nó có lỗi. Tôi đã cập nhật nó thành một tập lệnh bên ngoài để nó cũng dễ sử dụng hơn.
krowe

@ jpmc26 Tôi đã thêm một số kiểm tra để kiểm tra đầu vào lẻ ​​khác.
krowe

0

Bỏ qua các dòng trống

Đây là một cách tiếp cận bằng cách sử dụng awk:

echo "$TEST" | tac | awk 'f==0 && /./ {f=NR} END{if(f==NR){exit 0}; exit 1 }' && echo "Found A Single Line"

Làm thế nào nó hoạt động:

  • tiếng vang "$ KIỂM TRA"

    Điều này có bất kỳ biến shell nào mà chúng ta quan tâm và gửi nó tới tiêu chuẩn.

  • tac

    Điều này đảo ngược thứ tự của các dòng để dòng cuối cùng được trả về trước. Sau khi thực hiện tac, các dòng dấu trở thành các dòng hàng đầu.

    (Tên taclà ngược lại catvới lý do taclàm những gì catnhưng ngược lại.)

  • awk 'f==0 && /./ {f=NR} END{if(f==NR){exit 0}; exit 1 }'

    Điều này lưu số dòng của dòng không trống đầu tiên trong biến f. Sau khi đọc tất cả các dòng, nó so sánh fvới tổng số dòng , NR. nếu fbằng NR, thì chúng ta chỉ có một dòng duy nhất (bỏ qua các khoảng trống ban đầu) và chúng ta thoát với mã 0. Nếu có một hoặc nhiều dòng sau dòng trống đầu tiên, thì nó sẽ thoát với mã `.

  • && echo "Found A Single Line"

    Nếu awkthoát với mã 0, thì echocâu lệnh được thực thi.

Bỏ qua cả hai dòng trống hàng đầu và dấu

Bằng cách tạo thêm một awkbiến, chúng tôi có thể mở rộng thử nghiệm để bỏ qua cả hai dòng trống hàng đầu và cuối:

echo "$TEST" | awk 'first==0 && /./ {first=NR} /./ {last=NR} END{if(first==last){exit 0}; exit 1 }' && echo " Found A Single Line"

Bởi vì phiên bản awkmã này xử lý cả khoảng trống hàng đầu và dấu kiểm, tackhông còn cần thiết nữa.

Lấy awkmã một mảnh tại một thời điểm:

  • first==0 && /./ {first=NR}

    Nếu biến firstlà 0 (hoặc nó chưa được đặt) và dòng có một ký tự, bất kỳ ký tự nào, sau đó được đặt thành firstsố dòng. Khi awkđọc xong các dòng, firstsẽ được đặt thành số dòng của dòng không trống đầu tiên.

  • /./ {last=NR}

    Nếu dòng có bất kỳ ký tự nào trong đó, sau đó đặt biến lastthành số dòng hiện tại. Khi awkđọc xong tất cả các dòng, biến này sẽ có số dòng của dòng không trống cuối cùng.

  • END{if(first==last){exit 0}; exit 1 }

    Điều này được thực hiện sau khi tất cả các dòng đã được đọc. Nếu firstbằng last, thì chúng ta đã thấy các dòng không hoặc dòng không trống và awkthoát với mã 0. Nếu không, nó thoát với mã 1. Kịch bản shell có thể kiểm tra mã thoát như bình thường bằng các ifcâu lệnh &&hoặc ||.

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.