遍历字符串并删除字母

遍历字符串并删除字母

我正在尝试从字符串中删除一些特定字符。这个想法是用户输入权限和文件名,然后我删除错误的权限(那些不是rwx)。我的脚本如下:

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,并将结果分配给。wx$1perms

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"

这构建了一个新的如果原始字符串中的当前字符是这些字符之一,并且该字符不存在于新字符串中(对于 的操作来说不是必需的),则通过添加rw或来从旧字符串中删除旧字符串。xchmod

seq我们不使用 ,而是使用for从零到比原始字符串长度小一的循环,并且为了便于阅读并且不重复,我们ch在每次迭代中提取当前字符。

我们没有对字符进行三个测试,而是执行单个模式匹配来查看它是否是r,wx

答案2

${permisos/perm_actual/}perm_actual从变量的值中删除文字字符串,我想你想要的${permisos/$perm_actual/}是。

但是您可以使用permisos=${permisos//[^rwx]}而不是循环来rwx一次性删除每个非字符,并[[ $permisos = *[^rwx]* ]]检查变量是否包含其中的任何一个。

( 和${foo//bar}都是[[ .. ]]非标准扩展,但您已经使用过它们,因此您可能正在运行 Bash/ksh/zsh。)

相关内容