我想提取变量中的部分字符串,如下所示,但它返回了错误的替换。
for i in `ls`;do echo ${i|cut -d. -f1};done
-bash: ${i|cut -d. -f1}: bad substitution
在我的场景中,我想重命名一批文件的后缀。
例如:更改abc.txt
为abc.csv
那么,我能做什么作为正确的语法呢?
顺便说一句,我不知道${i}
这种格式叫什么?
答案1
您似乎想删除当前目录中可用名称中第一个点之后的所有内容。
要循环当前目录中的所有名称,请使用
for name in *; do ...; done
将 的输出用于ls
目视检查以外的其他用途很容易出错,应避免。看为什么*不*解析`ls`(以及做什么来代替)?
要删除第一个点之后的位$name
(包括点本身),请使用${name%%.*}
.这是一个标准参数扩展.*
从变量的值中删除与通配模式匹配的最长后缀name
。
要输出此扩展的结果,您可以使用
printf '%s\n' "${name%%.*}"
查看两者什么时候需要双引号?和为什么 printf 比 echo 更好?。
你的完整脚本可以写成
#!/bin/sh
for name in *; do
printf '%s\n' "${name%%.*}"
done
你的第二个问题,关于什么${i}
叫:它是变量扩展(有时使用术语“参数扩展”或“变量/参数替换”)。将${i}
扩展为/替换为变量 的值i
。这也可以写成$i
花括号在这里没有做任何特殊的事情。您可能想要使用的唯一地方${i}
是$i
扩展是字符串的一部分并且紧接着的字符在变量名称中有效,如"${i}_stuff"
($i_stuff
将尝试扩展变量i_stuff
) 中。
答案2
您可以使用${i%%.*}
。它将删除第一次出现点(包括点)后的所有内容。
例如
i=absdfsfd.b.c.dddd
echo "${i%%.*}"
将给出输出
absdfsfd
在你的情况下:
for i in *;do echo "${i%%.*}";done
那就别用了for i in ls
。看为什么*不*解析`ls`(以及做什么来代替)?