Nếu, trong trường hợp không may, bạn chỉ đang cố gắng xử lý các trích dẫn để tái sử dụng ion vỏ, thì bạn có thể làm điều này mà không cần loại bỏ chúng, và nó cũng rất đơn giản:
aq() { sh -c 'for a do
alias "$((i=$i+1))=$a"
done; alias' -- "$@"
}
Hàm shell đó trích dẫn bất kỳ mảng arg nào bạn trao cho nó và tăng đầu ra của nó cho mỗi đối số có thể lặp lại.
Đây là với một vài lập luận:
aq \
"here's an
ugly one" \
"this one is \$PATHpretty bad, too" \
'this one```****```; totally sucks'
ĐẦU RA
1='here'"'"'s an
ugly one'
2='this one is $PATHpretty bad, too'
3='this one```****```; totally sucks'
Đầu ra đó là từ dash
mà thông thường trích dẫn an toàn trích dẫn đầu ra như thế '"'"'
. bash
sẽ làm gì '\''
.
Việc thay thế một lựa chọn các byte đơn, không phải khoảng trắng, không null bằng một byte đơn khác có thể được thực hiện nhanh nhất trong bất kỳ shell POSIX nào bằng $IFS
và $*
.
set -f; IFS=\"\'\`; set -- $var; printf %s "$*"
ĐẦU RA
"some ""crazy """"""""string ""here
Ở đó tôi chỉ printf
có nó để bạn có thể nhìn thấy nó, nhưng tất nhiên, nếu tôi đã làm:
var="$*"
... Thay vì giá trị của printf
lệnh $var
sẽ là những gì bạn thấy trong đầu ra ở đó.
Khi tôi set -f
chỉ thị shell không phải toàn cầu - trong trường hợp chuỗi chứa các ký tự có thể được hiểu là các mẫu hình cầu. Tôi làm điều này bởi vì trình phân tích cú pháp shell sẽ mở rộng các mẫu toàn cục sau khi nó thực hiện phân tách trường trên các biến. Globing có thể được kích hoạt lại như thế nào set +f
. Nói chung - trong các tập lệnh - tôi thấy hữu ích khi đặt bang của mình như:
#!/usr/bin/sh -f
Và sau đó để kích hoạt toàn cầu với set +f
bất kỳ dòng nào tôi có thể muốn.
Trường tách xảy ra dựa trên các ký tự trong $IFS
.
Có hai loại $IFS
giá trị - $IFS
khoảng trắng và $IFS
không khoảng trắng. $IFS
Các trường được phân cách bằng khoảng trắng ( dấu cách, tab, dòng mới) được chỉ định để tách biệt theo trình tự thành một trường duy nhất (hoặc không có gì cả nếu chúng không đi trước một cái gì khác) - vì vậy ...
IFS=\ ; var=' '; printf '<%s>' $var
<>
Nhưng tất cả những thứ khác được chỉ định để đánh giá một trường duy nhất cho mỗi lần xuất hiện - chúng không bị cắt cụt.
IFS=/; var='/////'; printf '<%s>' $var
<><><><><>
Theo mặc định, tất cả các mở rộng biến là $IFS
các mảng dữ liệu được phân tách - chúng phân tách thành các trường riêng biệt theo $IFS
. Khi bạn "
trích dẫn một, bạn ghi đè lên thuộc tính mảng đó và đánh giá nó dưới dạng một chuỗi.
Vì vậy, khi tôi làm ...
IFS=\"\'\`; set -- $var
Tôi đang đặt mảng đối số của shell thành nhiều $IFS
trường được phân tách bằng cách $var
mở rộng. Khi nó được mở rộng, các giá trị cấu thành của nó cho các ký tự chứa trong $IFS
đó bị mất - hiện tại chúng chỉ là các dấu tách trường - chúng là \0NUL
.
"$*"
- giống như các mở rộng biến được trích dẫn kép khác - cũng ghi đè lên các phẩm chất phân tách trường của $IFS
. Nhưng, ngoài ra , nó thay thế byte đầu tiên $IFS
cho mỗi trường được phân tách trong "$@"
. Vì vậy, vì "
là lần đầu tiên giá trị trong $IFS
tất cả các delimiters tiếp theo trở nên "
trong "$*"
. Và "
không cần thiết $IFS
khi bạn chia nó. Bạn có thể thay đổi hoàn toàn $IFS
sau set -- $args
một giá trị khác và byte đầu tiên mới của nó sau đó sẽ hiển thị cho các dấu phân cách trường trong "$*"
. Hơn thế nữa, bạn có thể xóa tất cả dấu vết của chúng hoàn toàn như:
set -- $var; IFS=; printf %s "$*"
ĐẦU RA
some crazy string here
tr
. PE của BASH tốt nhưng tr nhanh hơn nhiều trong trường hợp này. ví dụ:echo "$OUTPUT" | tr -dc '[[:alpha:]]'
vì bạn chỉ muốn có chữ và số