如何在 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
。
NOTE:expr
如果输出为 0(或 -0、00...),将以非零退出状态返回。
顺便提一句。这本书在 Ubuntu 官方存储库中以abs-guide
.
答案2
在 POSIX 中sh
,
"${var%?????}"
删除$var
最后 5 个尾随字符(或者$var
如果$var
包含的字符少于 5 个)"${var%"${var#??????????}"}"
是 的前 10 个字符$var
。"${var%_*}"
删除( -> )末尾$var
匹配的最短字符串。_*
$var
foo_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
,bash
或zsh
:
"${var:0:10}"
: 的前 10 个字符$var
与bash
或zsh
:
"${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