我正在尝试从字符串中删除一些特定字符。这个想法是用户输入权限和文件名,然后我删除错误的权限(那些不是r
、w
或x
)。我的脚本如下:
permisos=$1
for i in `seq 1 ${#1}`; do
perm_actual=${1:i-1:1}
[[ $perm_actual != *"r"* ]] && [[ $perm_actual != *"w"* ]] && [[ $perm_actual != *"x"* ]] && echo "El permiso $perm_actual es incorrecto, ignorándolo..."
permisos=${permisos/perm_actual/}
done
chmod u+$permisos $2
有谁知道为什么不从变量中删除错误的权限permisos
?
提前致谢
答案1
从字符串中删除字母很容易一次性完成,无需迭代字符串的字符。这可以tr
这样完成:
#!/bin/sh
perms="$( printf '%s' "$1" | tr -c -d 'rwx' )"
chmod u+"$perms" "$2"
这tr
首先用于删除第一个命令行参数中不包含任何字符r
, w
, 或 的所有内容x
,然后执行chmod
.
请注意扩展的引用,尤其是"$2"
.如果没有这些引号,您将无法在名称中包含空格或文件名通配符的文件上使用脚本(请参见“为什么我的 shell 脚本会因为空格或其他特殊字符而卡住?”)。
在 中bash
,您可以使用参数替换,例如
perms=${1//[!rwx]/}
这会删除所有不是或的内容r
,并将结果分配给。w
x
$1
perms
bash
然后脚本就变成了
#!/bin/bash
chmod u+"${1//[!rwx]/}" "$2"
通过使用
shift
chmod u+"$perms" "$@"
其中$perms
是通过上述任何一种方式计算的(前)shift
,您甚至可以让脚本同时对多个文件执行更改。shift
从列表中删除第一个命令行参数,并将扩展"$@"
到其余参数,每个参数都单独引用。
如果你绝对需要要迭代字符串的字符(你不需要),那么你可以这样做:
#!/bin/bash
string="$1"
for (( i = 0; i < ${#string}; ++i )); do
ch="${string:i:1}"
if [[ "$ch" == [rwx] ]] && [[ "$new_string" != *$ch* ]]; then
new_string+=$ch
fi
done
printf 'The new string is "%s"\n' "$new_string"
这构建了一个新的如果原始字符串中的当前字符是这些字符之一,并且该字符不存在于新字符串中(对于 的操作来说不是必需的),则通过添加r
、w
或来从旧字符串中删除旧字符串。x
chmod
seq
我们不使用 ,而是使用for
从零到比原始字符串长度小一的循环,并且为了便于阅读并且不重复,我们ch
在每次迭代中提取当前字符。
我们没有对字符进行三个测试,而是执行单个模式匹配来查看它是否是r
,w
或x
。
答案2
${permisos/perm_actual/}
perm_actual
从变量的值中删除文字字符串,我想你想要的${permisos/$perm_actual/}
是。
但是您可以使用permisos=${permisos//[^rwx]}
而不是循环来rwx
一次性删除每个非字符,并[[ $permisos = *[^rwx]* ]]
检查变量是否包含其中的任何一个。
( 和${foo//bar}
都是[[ .. ]]
非标准扩展,但您已经使用过它们,因此您可能正在运行 Bash/ksh/zsh。)