Iterar através de uma string e remover uma letra

0

Estou tentando remover alguns caracteres específicos de uma string. A ideia é que o usuário insira permissões e um nome de arquivo e eu remova as permissões ruins (aquelas que não são r , w ou x ). Meu script seria o seguinte:

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 

Alguém sabe por que não está removendo as permissões ruins da variável permisos ?

Obrigado antecipadamente

    
por servicioswebavr 20.05.2018 / 13:03

2 respostas

4

Remover letras de strings é fácil de fazer de uma só vez sem iterar os caracteres da string. Isso pode ser feito com tr assim:

#!/bin/sh

perms="$( printf '%s' "$1" | tr -c -d 'rwx' )"

chmod u+"$perms" "$2"

Isso usa tr para primeiro remover tudo do primeiro argumento da linha de comando que não é nenhum dos caracteres r , w ou x e, em seguida, executa o chmod .

Observe as citações das expansões, especialmente "$2" . Sem essas citações, você não seria capaz de usar seu script em arquivos com espaços ou caracteres globbing de nomes de arquivo em seus nomes (consulte, por exemplo, " Por que meu script de shell sufocar em espaços em branco ou outros caracteres especiais? ").

Em bash , você pode usar uma substituição de parâmetro como

perms=${1//[!rwx]/}

Isso remove tudo o que não é r , w ou x de $1 e atribui o resultado a perms .

O script bash torna-se

#!/bin/bash
chmod u+"${1//[!rwx]/}" "$2"

Usando

shift
chmod u+"$perms" "$@"

onde $perms é calculado de qualquer uma das maneiras acima ( antes do shift ), você pode até fazer com que o seu script execute a alteração em vários arquivos de uma vez. O shift remove o primeiro argumento de linha de comando da lista e "$@" expandirá para o restante dos argumentos, cada um citado individualmente.

Se você precisar absolutamente para iterar os caracteres da string (você não precisa), então você pode fazer assim:

#!/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"

Isso cria uma nova seqüência de caracteres antiga adicionando r , w ou x a ela se o caractere atual na sequência original for um desses caracteres e, se o caractere ainda não existe na nova string (não é necessário para a operação de chmod ).

Em vez de usar seq , usamos um loop for que vai de zero a um menor que o tamanho da string original e, para facilitar a leitura e não nos repetir, extraímos o caractere atual em ch em cada iteração.

Em vez de três testes no personagem, realizamos uma única correspondência de padrão para ver se é r , w ou x .

    
por 20.05.2018 / 13:10
2

${permisos/perm_actual/} remove a string literal perm_actual do valor da variável, acho que você quer ${permisos/$perm_actual/} .

Mas você poderia usar apenas permisos=${permisos//[^rwx]} em vez do loop para remover todos os caracteres não- rwx de uma só vez e [[ $permisos = *[^rwx]* ]] para verificar se a variável possui algum deles.

(Ambos ${foo//bar} e [[ .. ]] são extensões fora do padrão, mas você já as usou, então provavelmente você está executando o Bash / ksh / zsh.)

    
por 20.05.2018 / 13:09