%在Linux shell字符串中有什么作用?


28

在Linux Shell中,%的作用如下:

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

4
每次查找时,我通常都会通过搜索%%或找到bash手册页的正确部分##,因为这样令人难忘且难得,可以快速找到正确的部分。 man bash /##
彼得·科德斯

3
@PeterCordes我总是用“ 5%,所以%在结尾处,因此从结尾处削减。这是#5,所以#在开头并从开头处削减。” 但是有时候我什至把这一个混在一起……
glglgl

2
@glglgl:在典型的USA键盘上,#紧接在的左侧$%紧随其右。不需要助记符---往下看。(这可能至少是选择这些符号的原因的一部分。)
Kevin J. Chase,

@ KevinJ.Chase并非全世界的每个人都有一个典型的美国键盘。但是的确,在德语键盘上,%也是$的右边,这可能是开始记忆的起点。
glglgl

Answers:


29

%在模式被用来${variable%substring}将返回的内容variable与最短次数substring从后面删除variable

此功能支持通配符模式-这就是为什么它接受星号(星号)作为零个或多个字符的替代。

应该提到的是,这是Bash特有的-其他linux shell不一定包含此功能。

如果您想了解有关Bash中字符串操作的更多信息,我强烈建议您阅读页面。在其他方便的功能中-例如-解释了如何%%做:)

编辑:我忘了提,当它在模式的二手$((variable%number))$((variable1%$variable2))%字符会模运算符的功能。DavidPostill的答案中有更具体的文档链接。

%在不同上下文中使用时,应仅将其识别为常规字符。


2
运算符支持通配符模式,不支持正则表达式。
gardenhead

就像提到的gardenhead一样-它支持glob模式,而不是正则表达式。在正则表达式中,星号表示前一个字符的零个或多个。
slebetman'8

5
大多数Unix&Linux堆栈交换用户都不推荐您已链接的指南。我推荐使用《Wooledge Bash指南》
通配符

3
删除前缀和后缀的运算符是standard,因此它们应可在任何sh兼容的shell中使用,而不仅限于Bash。(尽管可能不在csh等等)。
ilkkachu

1
使用的另一个上下文%是的格式说明符printf
暂停,直到另行通知。

9

Bash参考手册:Shell参数扩展

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

被扩展为一个模式,就像文件名扩展。如果该模式与parameter的扩展值的结尾部分匹配,则扩展的结果是删除了最短匹配模式(情况)或最长匹配模式(情况)的参数值。如果参数为或模式去除操作依次应用于每个位置参数,则扩展为结果列表。如果parameter是下标为 或的数组变量‘%’‘%%’‘@’‘*’,‘@’‘*’, 模式删除操作依次应用于数组的每个成员,扩展是结果列表。


2
注意,一些参数扩展(包括%)是许多Shell支持的posix功能。
kojiro

7

通过实验,我发现当字符串用大括号(大括号)括起来时,%之后的匹配项将被丢弃。

为了显示:

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

这是输出:

abcd
abcd%
abcd
abcd

ab
abcd
ab
abcd
abcd%c*

7

在Linux shell(bash)中,该怎么%办?

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

在这种特殊情况下,%is 模式匹配运算符(请注意,它也可以是运算符)。


模式匹配运算符

$ {var%$ Pattern},$ {var %% $ Pattern}

${var%$Pattern}从与的后端匹配$var的最短部分中删除。$Pattern$var

${var%%$Pattern}从与的后端匹配$var的最长部分中删除。$Pattern$var

示例:参数替换中的模式匹配

#!/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

参数替换


模运算符

%

取模或模(返回整数除法运算的余数)

bash$ expr 5 % 3
2

5/3 = 1,其余2

运营商


也许我明白了:这是针对诸如此类的东西.*%并将其定义为非贪婪,而%%使其变得贪婪?因此,实际上,在重命名示例中,是否使用%或是否无关紧要,%%但是如果mv "$file" "${file%.*png.jpg}.jpg"使用%%(请注意*),则会将所有文件重命名为just .jpg,对吗?
Thomas Weller

@ThomasWeller我认为是正确的。但是我不是bash专家。
DavidPostill

说“删除...的最短部分$Pattern”是错误的,因为$Pattern在示例中未定义变量$var,执行${var%Pattern}或时仅删除了文本“模式” ${var%%Pattern}。也许这只是一个错字,但这是tldp.org错误的另一个例子。BashGuideBash Hackers Wiki都是更好的恕我直言。
约翰B

@JohnB谢谢。这两个链接都已添加书签。我已经纠正了答案中的文字。
DavidPostill
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.