Lỗi cú pháp gần mã thông báo bất ngờ `('


15

Khi tôi sử dụng mã dưới đây trong thiết bị đầu cuối SSH cho CentOS, nó hoạt động tốt:

paste <(printf "%s\n" "TOP")

Nhưng nếu tôi đặt cùng một mã dòng trong tập lệnh shell (test.sh) và chạy tập lệnh shell từ thiết bị đầu cuối, nó sẽ báo lỗi như thế này

./test.sh: line 30: syntax error near unexpected token ('   
./test.sh: line 30:     paste <(printf "%s\n" "TOP")

Làm thế nào tôi có thể khắc phục vấn đề này?


Làm thế nào chính xác là bạn đang chạy nó? gì '#!' dòng (nếu có) bắt đầu tập lệnh của bạn? Có vẻ như bạn đang gọi một trình thông dịch shell không hỗ trợ cú pháp đó (ví dụ dashthay vì bash).
Steeldo

Tôi có #!/bin/shở trên cùng. Tôi đã thực hiện như bash test.shnhưng nó cũng không hoạt động.
NecNecco

bashtrong chế độ POSIX không hỗ trợ cú pháp đó (khi được gọi bằng --posixhoặc dưới dạng /bin/sh). Sử dụng #!/bin/bash.
jordanm

@NecNecco: Bạn có POSIXLY_CORRECTbộ biến khi bạn bắt đầu bashkhông?
cuonglm

@jordanm chuyển sang #!/bin/bashở đầu đã khắc phục sự cố.
NecNecco

Câu trả lời:


23

Thay thế tiến trình không được chỉ định bởi POSIX, vì vậy không phải tất cả POSIX vỏ hỗ trợ nó, chỉ có một số vỏ như bash, zsh, ksh88, ksh93hỗ trợ.

Trong Centoshệ thống, /bin/shlà liên kết tượng trưng đến /bin/bash. Khi bashđược gọi với tên sh, bashvào chế độ posix ( Bash Startup Files - Được gọi với tên sh ). Trong chế độ posix, process substitutionkhông được hỗ trợ, gây ra lỗi cú pháp.

Script sẽ hoạt động, nếu bạn gọi bashtrực tiếp bash test.sh. Nếu không, có lẽ bashđã vào chế độ posix. Điều này có thể xảy ra nếu bạn bắt đầu bashvới --posixđối số hoặc biến POSIXLY_CORRECTđược đặt khi bashbắt đầu:

$ bash --posix test.sh 
test.sh: line 54: syntax error near unexpected token `('
test.sh: line 54: `paste <(printf "%s\n" "TOP")'

$ POSIXLY_CORRECT=1 bash test.sh 
test.sh: line 54: syntax error near unexpected token `('
test.sh: line 54: `paste <(printf "%s\n" "TOP")

Hoặc bashđược xây dựng với --enable-strict-posix-defaulttùy chọn.

Tại đây, bạn không cần thay thế quy trình, bạn có thể sử dụng ống vỏ tiêu chuẩn:

printf "%s\n" "TOP" | paste -

-là cách tiêu chuẩn để nói pasteđể đọc dữ liệu từ stdin. Với một số pastetriển khai, bạn có thể bỏ qua mặc dù điều đó không chuẩn.

Trường hợp sẽ hữu ích khi dán đầu ra của nhiều lệnh như trong:

paste <(cmd1) <(cmd2)

Trên các hệ thống hỗ trợ /dev/fd/n, có thể được thực hiện shvới:

{ cmd1 4<&- | { cmd2 3<&- | paste /dev/fd/3 -; } 3<&0 <&4 4<&-; } 4<&0

(đó là những gì <(...)làm trong nội bộ).


2

Đây là một cách giải quyết khác. Thay vì chạy lệnh, hãy chạy bash và truyền lệnh để bash bằng -c:

bash -c 'paste <(printf "%s\n" "TOP")'
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.