在 bash 中索引一个字符串

Pie*_*e B 22 shell bash string

如何在 sh/bash 中按索引引用字符串?也就是说,基本上是分裂它。

我正在尝试删除文件名的 5 个字符。所有名称都具有以下结构:name_nr_code。我正在尝试删除 5 个字母数字代码位。name_nr_总是 10 个字符。

有没有这样的事情?

for i in * ; do mv "$i" "$i"[:10] ; done

小智 22

就这么简单。

(重击)

for i in * ; do mv -- "$i" "${i:0:5}" ; done
Run Code Online (Sandbox Code Playgroud)

瞧。

以及高级 Bash 脚本指南第 10 章操作变量)中的解释,(带有额外的NOTEs 内联以突出该手册中的错误):

子串提取

${string:position}
Run Code Online (Sandbox Code Playgroud)

$stringat 中提取子字符串$position

如果$string参数是“*”或“@”,那么这将提取位置参数,从 开始$position

${string:position:length}
Run Code Online (Sandbox Code Playgroud)

$length$stringat 中提取子字符串的字符$position

NOTE缺少参数扩展的引号! echo不应用于任意数据。

stringZ=abcABC123ABCabc
#       0123456789.....
#       0-based indexing.

echo ${stringZ:0}                       # abcABC123ABCabc
echo ${stringZ:1}                       # bcABC123ABCabc
echo ${stringZ:7}                       # 23ABCabc 

echo ${stringZ:7:3}                     # 23A
                                        # Three characters of substring.


# Is it possible to index from the right end of the string?

echo ${stringZ:-4}                      # abcABC123ABCabc
# Defaults to full string, as in ${parameter:-default}.
# However . . . 

echo ${stringZ:(-4)}                    # Cabc
echo ${stringZ: -4}                     # Cabc
# Now, it works.
# Parentheses or added space "escape" the position parameter.
Run Code Online (Sandbox Code Playgroud)

位置长度的参数可以被“参数化”,即,表示为一个变量,而不是作为一个数值常数。


如果$string参数是“*”或“@”,那么这将提取最多的$length位置参数,从 开始$position

echo ${*:2}          # Echoes second and following positional parameters.
echo ${@:2}          # Same as above.

echo ${*:2:3}        # Echoes three positional parameters, starting at second.
Run Code Online (Sandbox Code Playgroud)

NOTE:expr substr是 GNU 扩展。

expr substr $string $position $length
Run Code Online (Sandbox Code Playgroud)

$length$string开始提取字符$position

stringZ=abcABC123ABCabc
#       123456789......
#       1-based indexing.

echo `expr substr $stringZ 1 2`           # ab
echo `expr substr $stringZ 4 3`           # ABC
Run Code Online (Sandbox Code Playgroud)

NOTE: 那echo是多余的,使它更不可靠。使用expr substr + "$string1" 1 2.

NOTE:expr如果输出为 0(或 -0, 00...),将返回非零退出状态。


顺便提一句。这本书在官方 Ubuntu 存储库中作为abs-guide.


Sté*_*las 12

在 POSIX 中sh

  • "${var%?????}"$var剥离的最后5个尾部字符的(或$var如果$var包含少于5个字符)

  • "${var%"${var#??????????}"}"是 的前 10 个字符$var

  • "${var%_*}"$var剥离匹配的最短串的_*在端部$varfoo_bar_baz- > foo_bar)。
  • "${var%%_*}": 相同但最长的匹配而不是最短的匹配 ( foo_bar_baz-> foo)。
  • 如果你想获得foo_bar_"${var%"${var##*_}"}"${var##pattern}是一样的${var%%pattern},但找之初的模式$var,而不是末端)。

zsh

  • $var[1,-6] 用于第一个字符到最后的第 6 个字符(除最后 5 个字符外的所有字符)。
  • $var[1,10] 前 10 个字符。

ksh,bashzsh:

  • "${var:0:10}": 的前 10 个字符 $var

bashzsh

  • "${var:0:-5}": 除最后 5 个字符外的所有字符(如果$var设置但包含少于 5 个字符,则给出错误并退出脚本,也$var未设置时zsh)。

如果您需要 Bournesh兼容性,则很难做到可靠。如果您可以保证结果不会以换行符结尾,您可以执行以下操作:

first_10=`expr " $var" : ' \(.{1,10\}\)'` # beware the exit status
                                          # may be non-zero if the
                                          # result is 0 or 0000000000

all_but_last_5=`expr " $var" : ' \(.*\).\{5\}'`
Run Code Online (Sandbox Code Playgroud)

您还将限制$var(因系统而异)的长度。

在所有这些解决方案中,如果$var包含不能构成有效字符一部分的字节,YMMV。