在 bash 中索引字符串

在 bash 中索引字符串

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

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

有没有类似的事情;

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

答案1

就这么简单。

(重击)

for i in * ; do mv -- "$i" "${i:0:5}" ; done

瞧。

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

子串提取

${string:position}

从中提取子字符串$string$position

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

${string:position:length}

提取物$length子串的字符来自$string$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.

位置长度参数可以“参数化”,即表示为变量,而不是数字常量。


如果$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.

NOTE:expr substr是 GNU 扩展。

expr substr $string $position $length

提取物$length字符来自$string开始于$position

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

echo `expr substr $stringZ 1 2`           # ab
echo `expr substr $stringZ 4 3`           # ABC

NOTE:这echo是多余的,而且更不可靠。使用expr substr + "$string1" 1 2

NOTEexpr如果输出为 0(或 -0、00...),将以非零退出状态返回。


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

答案2

在 POSIX 中sh

  • "${var%?????}"删除$var最后 5 个尾随字符(或者$var如果$var包含的字符少于 5 个)

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

  • "${var%_*}"删除( -> )末尾$var匹配的最短字符串。_*$varfoo_bar_bazfoo_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}"$var:除最后 5 个字符之外的所有字符(如果设置了但包含的字符少于 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\}'`

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

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

答案3

sh不提供从字符串中获取子字符串的内置方法(据我所知),但bash您可以这样做

${i:0:10}

这将为您提供变量值的前十个字符i

一般格式为${variable:offset:length}.

答案4

首先,不要for对文件名使用循环。

那么,类似这样的事情应该会有所帮助。

find ./ -type f | while read filename ;do
  newfilename=$(echo ${filename}|cut -c 1-10)
  mv ${filename} ${newfilename}
done

相关内容