Bạn có thể gọi các tiện ích bên ngoài (xem các câu trả lời khác), nhưng chúng sẽ làm cho tập lệnh của bạn chậm hơn và thật khó để có được hệ thống ống nước đúng.
Zsh
Trong zsh, bạn có thể viết ${#$(readlink -f /etc/fstab)}
để lấy độ dài của lệnh thay thế. Lưu ý rằng đây không phải là độ dài của đầu ra lệnh, nó là độ dài của đầu ra mà không có bất kỳ dòng mới nào.
Nếu bạn muốn độ dài chính xác của đầu ra, hãy xuất thêm một ký tự không phải dòng mới ở cuối và trừ đi một ký tự.
$((${#$(readlink -f /etc/fstab; echo .)} - 1))
Nếu những gì bạn muốn là tải trọng trong đầu ra của lệnh, thì bạn cần trừ hai ở đây, bởi vì đầu ra của readlink -f
là đường dẫn chính tắc cộng với một dòng mới.
$((${#$(readlink -f /etc/fstab; echo .)} - 2))
Điều này khác với ${#$(readlink -f /etc/fstab)}
trong trường hợp hiếm hoi nhưng có thể xảy ra khi chính đường dẫn chính tắc kết thúc trong một dòng mới.
Đối với ví dụ cụ thể này, bạn hoàn toàn không cần một tiện ích bên ngoài, bởi vì zsh có cấu trúc tích hợp tương đương với readlink -f
, thông qua công cụ sửa đổi lịch sử A
.
echo /etc/fstab(:A)
Để có được độ dài, hãy sử dụng công cụ sửa đổi lịch sử trong việc mở rộng tham số:
${#${:-/etc/fstab}:A}
Nếu bạn có tên tệp trong một biến filename
, đó sẽ là ${#filename:A}
.
Vỏ kiểu Bourne / POSIX
Không có vỏ Bourne / POSIX thuần túy nào (Bourne, tro, mksh, ksh93, bash, yash,) có bất kỳ phần mở rộng tương tự nào mà tôi biết. Nếu bạn cần áp dụng thay thế tham số cho đầu ra của thay thế lệnh hoặc thay thế tham số lồng nhau, hãy sử dụng các giai đoạn kế tiếp.
Bạn có thể nhồi công cụ xử lý vào một chức năng nếu bạn muốn.
command_output_length_sans_trailing_newlines () {
set -- "$("$@")"
echo "${#1}"
}
hoặc là
command_output_length () {
set -- "$("$@"; echo .)"
echo "$((${#1} - 1))"
}
nhưng thường không có lợi ích gì; ngoại trừ với ksh93, điều đó làm cho một ngã ba phụ có thể sử dụng đầu ra của hàm, do đó, nó làm cho tập lệnh của bạn chậm hơn và hiếm khi có bất kỳ lợi ích dễ đọc nào.
Một lần nữa, đầu ra của readlink -f
là đường dẫn chính tắc cộng với một dòng mới; nếu bạn muốn độ dài của đường dẫn chính tắc, hãy trừ 2 thay vì 1 in command_output_length
. Việc sử dụng chỉ command_output_length_sans_trailing_newlines
mang lại kết quả đúng khi đường dẫn chính không kết thúc ở dòng mới.
Byte vs ký tự
${#…}
được cho là độ dài tính bằng ký tự, không tính bằng byte, điều này tạo ra sự khác biệt về vị trí đa bào. Các phiên bản cập nhật hợp lý của ksh93, bash và zsh tính toán độ dài tính bằng ký tự theo giá trị LC_CTYPE
tại thời điểm ${#…}
cấu trúc được mở rộng. Nhiều hệ vỏ phổ biến khác không thực sự hỗ trợ các địa điểm đa bào: như dấu gạch ngang 0,5,7, mksh 46 và posh 0.12.3, ${#…}
trả về độ dài tính bằng byte. Nếu bạn muốn độ dài của các ký tự một cách đáng tin cậy, hãy sử dụng wc
tiện ích:
$(readlink -f /etc/fstab | wc -m)
Miễn là $LC_CTYPE
chỉ định một miền địa phương hợp lệ, bạn có thể tin tưởng rằng điều này sẽ xảy ra lỗi (trên nền tảng cổ xưa hoặc bị hạn chế không hỗ trợ các địa điểm đa nhân) hoặc trả về độ dài chính xác trong các ký tự. (Đối với Unicode, độ dài của dòng chữ trong ký tự, có nghĩa là số lượng điểm mã - số lượng glyphs là một câu chuyện khác, do các biến chứng như kết hợp các ký tự.)
Nếu bạn muốn độ dài tính bằng byte, hãy đặt LC_CTYPE=C
tạm thời hoặc sử dụng wc -c
thay vì wc -m
.
Đếm các byte hoặc ký tự wc
bao gồm bất kỳ dòng mới nào từ lệnh. Nếu bạn muốn độ dài của đường dẫn chính tắc tính bằng byte, thì đó là
$(($(readlink -f /etc/fstab | wc -c) - 1))
Để có được nó trong các ký tự, trừ 2.
readlink -f /etc/fstab
là 11 ký tự. Đừng quên dòng mới. Nếu không, bạn sẽ thấy/etc/fstabluser@cern:~$
khi bạn chạy nó từ một cái vỏ.