Kiểm tra nếu biến chứa dòng mới (POSIX)


8

Tôi biết rằng một số vỏ chấp nhận loại thử nghiệm này:

t() { [[ $var == *$'\n'* ]] && res=yes || res=no
      printf '%s ' "$res";
    }

var='ab
cd'
t
var='abcd'
t
echo

khi thực hiện:

$ bash ./script
yes no
  1. POSIX (dấu gạch ngang) hoạt động tương đương là gì

  2. Đây có phải là một cách đáng tin cậy để kiểm tra?

    nl='
    '
    
    t() {  case "$var" in
               *$nl* ) res=yes ;;
               * ) res=no ;;
           esac
           printf '%s ' "$res"
         }
    
    var='ab
    cd'
    t
    var='abcd'
    t
    echo

Câu trả lời:


12

Bạn có thể đặt một dòng mới cứng trong một biến và mô hình khớp với case.

$ cat nl.sh
#!/bin/sh
nl='
'
case "$1" in
    *$nl*)  echo has newline ;;
    *)      echo no newline  ;;
esac

$ dash nl.sh $'foo\nbar'
has newline
$ dash nl.sh $'foobar'
no newline

Cách khác để tạo dòng mới là như thế này:

nl=$(printf "\nx"); nl=${nl%x}

Sự thay thế lệnh rõ ràng không hoạt động bởi vì các dòng mới theo dõi được loại bỏ bởi sự thay thế.


5

Đúng,

nl='
'
case $var in
  (*"$nl"*) echo yes;;
  (*)       echo no;;
esac

(theo nguyên tắc, tôi muốn trích dẫn tất cả các mở rộng biến trong casemẫu trừ khi tôi muốn chúng được coi là mẫu, mặc dù ở đây nó không tạo ra sự khác biệt vì $nlkhông chứa ký tự đại diện).

hoặc là

case $var in
  (*'
'*) echo yes;;
  (*) echo no;;
esac

Tất cả nên hoạt động và tuân thủ POSIX, và những gì tôi sẽ sử dụng cho điều đó. Nếu bạn loại bỏ (s, nó thậm chí sẽ hoạt động trong vỏ Bourne cũ.

Đối với một cách khác để đặt $nlbiến:

eval "$(printf 'nl="\n"')"

Lưu ý rằng $'\n'được lên kế hoạch đưa vào phiên bản tiếp theo của tiêu chuẩn POSIX . Nó đã được hỗ trợ bởi ksh93, zsh, bash, mksh, busybox và FreeBSD shít nhất (tính đến tháng 2 năm 2018).

Về việc thử nghiệm bạn có là đủ hay không, bạn đã có một thử nghiệm cho cả hai trường hợp, vì vậy sẽ thử nghiệm tất cả các đường dẫn mã.

Hiện tại có một thứ không được chỉ định rõ ràng trong thông số POSIX: liệu có *khớp với chuỗi có chứa chuỗi byte không tạo thành các ký tự hợp lệ hay liệu các biến shell có thể chứa các chuỗi đó hay không.

Trong thực tế, ngoài yashcác biến chỉ có thể chứa các ký tự và ngoài các byte NUL (không có shell nhưng zshcó thể lưu trữ trong các biến của chúng), *$nl*phải khớp với bất kỳ chuỗi nào chứa $nlngay cả khi chúng chứa các chuỗi byte không hợp lệ các ký tự (như $'\x80'trong UTF-8).

findVí dụ, một số triển khai sẽ không khớp với -name "*$nl*"chúng, vì vậy nếu thử nghiệm một vỏ mới và nếu bạn có ý định xử lý những thứ không được đảm bảo là văn bản (như tên tệp), bạn có thể muốn thêm trường hợp thử nghiệm cho nó. Thích với:

test=$(printf '\200\n\200')

trong một miền địa phương UTF-8.

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.