Tại sao -a trong nhóm #! / Bin / sh -a thì ảnh hưởng đến sed và bộ Set -a không?


20

Nếu tôi chạy tệp .sh sau:

#!/bin/sh -a
echo "a" | sed -e 's/[\d001-\d008]//g'

Kết quả là một lỗi:

sed: -e biểu thức # 1, char 18: Phạm vi kết thúc không hợp lệ

Nhưng nếu tôi chạy tệp .sh sau:

#!/bin/sh
set -a
echo "a" | sed -e 's/[\d001-\d008]//g'

Nó chạy không có lỗi. Không phải mã thứ hai được cho là tương đương với mã thứ nhất sao? Tại sao lỗi trong cái đầu tiên?


Không phải tất cả shđều giống nhau. Cũng không phải tất cả sed đều tương đương. Bạn shđang sử dụng cái gì Trong hệ điều hành nào? và sed nào (có thể? sed --versionnếu nó không thất bại)?
Isaac

1
thiết lập LC_COLLATE=C(hoặc POSIX) cho cuộc gọi để sedgiải quyết vấn đề
Jeff Schaller

4
Một điểm khác biệt tôi tìm thấy: tập lệnh đầu tiên gọi sed (và có lẽ là bất kỳ tiện ích nào khác) với POSIXLY_CORRECT=ymôi trường, tập lệnh thứ hai không có POSIXLY_CORRECTtrong môi trường. Shell tôi gọi cả hai script không có POSIXLY_CORRECTtrong môi trường của nó.
Đánh dấu Plotnick

1
À, echo "a" | POSIXLY_CORRECT=y sed -e 's/[\d001-\d008]//g' tái tạo vấn đề của bạn
Isaac

1
Xác nhận rằng các lỗi trên đối với tôi chính xác như OP đã hiển thị trên CentOS 7.x - GNU bash, phiên bản 4.2.46 (2) -release (x86_64-redhat-linux-gnu) & CentOS Linux phát hành 7.5.1804 (Lõi) .
slm

Câu trả lời:


31

Khi bash được gọi với tên sh, nó thực hiện điều này :

if (shell_name[0] == 's' && shell_name[1] == 'h' && shell_name[2] == '\0')
    act_like_sh++;

và sau đó đặt POSIXLY_CORRECTbiến shell thànhy :

if (act_like_sh)
  {
    bind_variable ("POSIXLY_CORRECT", "y", 0);
    sv_strict_posix ("POSIXLY_CORRECT");
  }

bind_variablecác lệnh gọi bind_variable_internal, nếu thuộc tính shell ađược bật tại thời điểm đó (sẽ là nếu bạn gọi shell với -a), đánh dấu biến shell là xuất .

Vì vậy, trong kịch bản đầu tiên của bạn:

#!/bin/sh -a
echo "a" | sed -e 's/[\d001-\d008]//g'

sedđược viện dẫn POSIXLY_CORRECT=ytrong môi trường của nó, điều này sẽ khiến nó phàn nàn [\d001-\d008]. (Điều tương tự xảy ra nếu sed được cung cấp --posixtùy chọn.)

Trong GNU sed, là escape code cho nhân vật có giá trị số trong cơ số 10 là NNN , nhưng trong chế độ POSIX, đây là khuyết tật bên trong một biểu thức khung, vì vậy , có nghĩa là theo nghĩa đen các nhân vật , vv, với phạm vi là từ để . Theo thứ tự mã ký tự, xuất hiện trước (và phạm vi bao gồm tất cả các chữ số trừ số 0, cộng với tất cả các chữ cái viết hoa, cộng với một số ký tự đặc biệt). Tuy nhiên, trong ngôn ngữ mà bạn đang sử dụng, hãy sắp xếp trước , vì vậy phạm vi không hợp lệ.\dNNN[\d001-\d008]\d1\1\en_US.UTF-8\1

Trong kịch bản thứ hai của bạn:

#!/bin/sh
set -a
echo "a" | sed -e 's/[\d001-\d008]//g'

mặc dù POSIXLY_CORRECTđược đặt trong trình bao, nó không được xuất, vì vậy sed được gọi mà không có POSIXLY_CORRECTtrong môi trường và sed chạy với các phần mở rộng GNU.

Nếu bạn thêm export POSIXLY_CORRECTgần đầu tập lệnh thứ hai của mình, bạn cũng sẽ thấy sed phàn nàn.


6
Đối với tôi, đó là một lỗi.
Stéphane Chazelas

1
kinh dị vỏ thánh, Batman! Đó là một cách giải quyết thú vị (và một chút thay đổi để thấy một vấn đề xuất phát từ việc /bin/shthực sự Bash). Điều tương tự cũng xảy ra nếu POSIXLY_CORRECTở trong môi trường trước khi shBash bắt đầu: nó cũng sẽ truyền nó như là POSIXLY_CORRECT=y.
ilkkachu

3
@StevenPenny, nhưng POSIXLY_CORRECT không ở trong môi trường khi trình bao khởi động và tập lệnh không đặt nó. Vỏ nào. Nó tạo ra một biến môi trường từ hư không, điều này cực kỳ tệ vì nó ở chế độ mà nó được cho là và cố gắng tuân thủ tiêu chuẩn.
ilkkachu

4
FWIW, Bash dường như cũng không tài liệu rằng nó sẽ tự thiết lập POSIXLY_CORRECT. Không có đề cập nào về nó trong danh sách các hiệu ứng của chế độ POSIXmô tả biến chỉ nói rằng cài đặt nó thay đổi vỏ sang chế độ POSIX, chứ không phải theo cách khác.
ilkkachu

1
@ilkkachu. Làm xong. Tôi nghĩ rằng thông số POSIX cũng nên được cập nhật để làm rõ những biến nào bị ảnh hưởng allexport.
Stéphane Chazelas
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.