% Làm gì trong chuỗi shell Linux?


28

Trong Linux shell,% làm gì, như trong:

for file in *.png.jpg; do
  mv "$file" "${file%.png.jpg}.jpg"
done

4
Mỗi lần tôi tìm kiếm điều này, tôi thường tìm đúng phần của trang bash man bằng cách tìm kiếm %%hoặc ##, vì điều đó đáng nhớ và hiếm khi đủ để tìm đúng phần một cách nhanh chóng. man bash /##
Peter Cordes

3
@PeterCordes Tôi luôn nhắc lại điều này bởi "Đó là 5%, vì vậy% ở cuối và do đó cắt giảm từ cuối. Và đó là số 5, vì vậy # là lúc bắt đầu và cắt giảm từ đầu." Nhưng đôi khi tôi thậm chí còn trộn lẫn một thứ này
glglgl

2
@glglgl: Trên bàn phím điển hình của Hoa Kỳ, #ngay bên trái $%ngay bên phải. Không cần ghi nhớ --- chỉ cần nhìn xuống. (Đó có lẽ là một phần lý do tại sao những biểu tượng đó được chọn.)
Kevin J. Chase

@ KevinJ.Chase Không phải ai trên thế giới cũng có bàn phím USA điển hình. Nhưng thực sự, trên bàn phím tiếng Đức,% cũng đúng với $, đó có thể là một khởi đầu để ghi nhớ.
glglgl

Câu trả lời:


29

Khi %được sử dụng trong mẫu, ${variable%substring}nó sẽ trả về nội dung variablevới thời gian ngắn nhất substringbị xóa từ phía sau variable.

Hàm này hỗ trợ các mẫu ký tự đại diện - đó là lý do tại sao nó chấp nhận dấu sao (dấu sao) dưới dạng thay thế cho 0 hoặc nhiều ký tự.

Cần phải đề cập rằng đây là đặc thù của Bash - các shell linux khác không nhất thiết phải chứa chức năng này.

Nếu bạn muốn tìm hiểu thêm về thao tác chuỗi trong Bash, tôi rất khuyên bạn nên đọc này trang. Trong số các chức năng tiện dụng khác, nó - ví dụ - giải thích những gì %%làm :)

Chỉnh sửa: Tôi quên kể rằng khi nó được sử dụng trong mô hình $((variable%number))hoặc $((variable1%$variable2))các %nhân vật sẽ hoạt động như khai thác modulo. DavidPostill có các liên kết tài liệu cụ thể hơn trong câu trả lời của mình.

Khi %được sử dụng trong các bối cảnh khác nhau, nó chỉ được công nhận là ký tự thông thường.


2
Toán tử hỗ trợ các mẫu ký tự đại diện , không phải biểu thức chính quy.
vườn

Giống như gardenenhead đã đề cập - nó hỗ trợ các mẫu hình cầu, không phải biểu thức chính quy. Trong biểu thức chính quy, một ngôi sao có nghĩa là 0 hoặc nhiều ký tự trước đó.
slebetman

5
Hướng dẫn mà bạn đã liên kết rất nhiều không được khuyến nghị bởi hầu hết người dùng trao đổi ngăn xếp Unix & Linux . Tôi đề nghị Hướng dẫn Wooledge Bash thay thế.
tự đại diện

3
Các toán tử loại bỏ tiền tố và hậu tố là tiêu chuẩn , vì vậy chúng có thể được sử dụng trong bất kỳ trình shbao tương thích nào , không chỉ Bash. (mặc dù có lẽ không trong cshvà tương tự).
ilkkachu

1
Một bối cảnh khác %được sử dụng là trong định dạng định dạng cho printf.
Tạm dừng cho đến khi có thông báo mới.

9

Hướng dẫn tham khảo Bash: Mở rộng tham số Shell

${parameter%word}
${parameter%%word}

Các từ được mở rộng để tạo ra một mô hình giống như trong việc mở rộng tên tập tin. Nếu mẫu khớp với phần đuôi của giá trị mở rộng của tham số , thì kết quả của việc mở rộng là giá trị của tham số có mẫu khớp ngắn nhất ( ‘%’trường hợp) hoặc mẫu khớp dài nhất ( ‘%%’trường hợp) đã bị xóa. Nếu tham số‘@’hoặc ‘*’,hoạt động loại bỏ mẫu được áp dụng lần lượt cho từng tham số vị trí và mở rộng là danh sách kết quả. Nếu tham số là một biến mảng được đăng ký bằng ‘@’ hoặc‘*’, lần lượt thao tác loại bỏ mẫu được áp dụng cho từng thành viên của mảng và việc mở rộng là danh sách kết quả.


2
NB một số mở rộng tham số bao gồm% là các tính năng posix mà nhiều shell hỗ trợ.
kojiro

7

Bằng cách thử nghiệm, tôi thấy rằng một kết quả khớp sau% bị loại bỏ, khi chuỗi được đặt trong dấu ngoặc nhọn (dấu ngoặc nhọn).

Để minh họa:

touch abcd         # Create file abcd

for file in ab*; do
 echo $file        # echoes the filename
 echo $file%       # echoes the filename plus "%"
 echo ${file%}     # echoes the filename
 echo "${file%}"   # echoes the filename
 echo
 echo "${file%c*}" # Discard anything after % matching c*
 echo "${file%*}"  # * is not greedy
 echo ${file%c*}   # Without quotes works too
 echo "${file%c}"  # No match after %, no effect
 echo $file%c*     # Without {} fails
done

Đây là đầu ra:

abcd
abcd%
abcd
abcd

ab
abcd
ab
abcd
abcd%c*

7

Trong Linux shell ( bash), %làm gì?

for file in *.png.jpg; do
  mv "$file" "${file%.png.jpg}.jpg"
done

Trong trường hợp cụ thể này, %mô hình phù hợp với điều hành (lưu ý nó cũng có thể là một modulo nhà điều hành).


Toán tử khớp mẫu

$ {var% $ Mẫu}, $ {var %% $ Mẫu}

${var%$Pattern}Xóa khỏi $varphần ngắn nhất $Patternphù hợp với mặt sau của $var.

${var%%$Pattern}Xóa khỏi $varphần dài nhất $Patternphù hợp với mặt sau của $var.

Ví dụ: Khớp mẫu thay thế tham số

#!/bin/bash
# patt-matching.sh

# Pattern matching  using the # ## % %% parameter substitution operators.

var1=abcd12345abc6789
pattern1=a*c  # * (wild card) matches everything between a - c.

echo
echo "var1 = $var1"           # abcd12345abc6789
echo "var1 = ${var1}"         # abcd12345abc6789
                              # (alternate form)
echo "Number of characters in ${var1} = ${#var1}"
echo

echo "pattern1 = $pattern1"   # a*c  (everything between 'a' and 'c')
echo "--------------"
echo '${var1#$pattern1}  =' "${var1#$pattern1}"    #         d12345abc6789
# Shortest possible match, strips out first 3 characters  abcd12345abc6789
#                                     ^^^^^               |-|
echo '${var1##$pattern1} =' "${var1##$pattern1}"   #                  6789      
# Longest possible match, strips out first 12 characters  abcd12345abc6789
#                                    ^^^^^                |----------|

echo; echo; echo

pattern2=b*9            # everything between 'b' and '9'
echo "var1 = $var1"     # Still  abcd12345abc6789
echo
echo "pattern2 = $pattern2"
echo "--------------"
echo '${var1%pattern2}  =' "${var1%$pattern2}"     #     abcd12345a
# Shortest possible match, strips out last 6 characters  abcd12345abc6789
#                                     ^^^^                         |----|
echo '${var1%%pattern2} =' "${var1%%$pattern2}"    #     a
# Longest possible match, strips out last 12 characters  abcd12345abc6789
#                                    ^^^^                 |-------------|

# Remember, # and ## work from the left end (beginning) of string,
#           % and %% work from the right end.

echo

exit 0

Nguồn tham số thay thế


Toán tử Modulo

%

modulo hoặc mod (trả về phần còn lại của phép toán chia số nguyên)

bash$ expr 5 % 3
2

5/3 = 1, với 2 phần còn lại

Người vận hành nguồn


Có lẽ tôi đã nhận nó: điều này là cho những thứ như .*%định nghĩa nó là không tham lam trong khi %%làm cho nó tham lam? Vì vậy, thực tế trong ví dụ đổi tên, không quan trọng nên sử dụng %hay %%nhưng nếu nó mv "$file" "${file%.*png.jpg}.jpg"(lưu ý *) sử dụng %% sẽ đổi tên tất cả các tệp thành đúng .jpg, phải không?
Thomas Weller

@ThomasWeller Tôi nghĩ đó là chính xác. Nhưng tôi không phải là chuyên gia bash.
DavidPostill

Nói "Xóa ... phần ngắn nhất của $Pattern" là sai vì biến $Patternkhông được xác định trong ví dụ, chỉ có văn bản "Mẫu" bị xóa khỏi $varkhi thực hiện ${var%Pattern}hoặc ${var%%Pattern}. Có thể đây chỉ là một lỗi đánh máy, nhưng đây là một ví dụ khác về tldp.org bị sai. BashGuide hoặc Bash Hackers Wiki đều là những tài liệu tham khảo tốt hơn nhiều.
John B

@JohnB Cảm ơn. Cả hai liên kết được đánh dấu. Tôi đã sửa văn bản trong câu trả lời.
DavidPostill
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.