продолжить <n>не пропуская <n>итераций вперед в сценарии оболочки - PullRequest
1 голос
/ 23 мая 2019

Я создал преобразователь hex в ASCII для строк в bash. Приложение, в котором я нахожусь, меняет символы (что угодно, кроме [0-9], [A-Z], [a-z]) в строке на соответствующий ей шестнадцатеричный%. Например: / изменяется на% 2F в строке

Я хочу сохранить символы ASCII как есть. Ниже мой код:

NAME=%2fhome%40%21%23
C_NAME=""
for (( i=0; i<${#NAME}; i++ )); do
    CHK=$(echo "{NAME:$i:1}" | grep -v "\%" &> /dev/null;echo $?)
    if [[ ${CHK} -eq 0 ]]; then
       C_NAME=`echo "$C_NAME${NAME:$i:1}"`
    else
       HEX=`echo "${NAME:$i:3}" | sed "s/%//"`
       C_NAME=`echo -n "$C_NAME";printf "\x$HEX"`
       continue 2
    fi
done
echo "$C_NAME"

ВЫВОД:

 /2fhome@40!21#23

ОЖИДАЕТСЯ:

  /home@!#

Так что в основном конверсия происходит, но не на месте. Он также сохраняет шестнадцатеричные значения, что говорит мне, что оператор continue 2, вероятно, не работает, как я ожидаю в моем коде. Любые обходные пути, пожалуйста.

Ответы [ 3 ]

2 голосов
/ 24 мая 2019

Использование структуры вашего скрипта с некоторыми упрощениями и исправлениями:

#!/bin/bash
name=%2fhome%40%21%23
c_name=""
for (( i=0; i<${#name}; i++ )); do
    c=${name:i:1}
    if [[ $c != % ]]; then
       c_name=$c_name$c
    else
       hex=${name:i+1:2}
       printf -v c_name "%s\x$hex" "$c_name"
       (( i += 2 ))    # stolen from Dudi Boy's answer
    fi
done
echo "$c_name"
  • Всегда используйте строчные или смешанные переменные, чтобы избежать вероятности конфликта имен с переменными оболочки или окружения
  • Всегда используйте $() вместо кавычек
  • Большинство команд echo, которые вы используете, не нужны
  • Вы можете избежать использования sed и grep
  • Переменные никогда не должны включаться в строку формата printf, но здесь этого нельзя легко избежать (хотя вы можете использовать echo -e "\x$hex" вместо этого)
  • Вы можете выполнять математику внутри расширений параметров
  • % не нужно экранировать в вашей grep команде
  • Вы можете исключить переменную $hex, если используете ее значение напрямую:
    printf -v c_name "%s\x${name:i+1:2}" "$c_name"
2 голосов
/ 23 мая 2019

У вас есть только один цикл, поэтому я предполагаю, что вы ожидали, что continue 2 пропустит текущую и следующую итерацию текущего цикла, однако в документации help continue четко говорится

continue [n]
[...]
Если указано N, возобновляется N-й замкнутый цикл.

Нет встроенной функции для пропуска текущего , а также следующего итерация текущего цикла, но в вашем случае вы можете использовать (( i += 2 )) вместо continue 2.

1 голос
/ 23 мая 2019

Мне очень понравилось ваше упражнение, и я решил решить его с помощью awk (мое текущее исследование).

Надеюсь, вам тоже понравится.

cat script.awk

BEGIN {RS = "%[[:xdigit:]]+"} { # redefine record separtor to RegEx (gawk specific)
        decNum = strtonum("0x"substr(RT, 2)); # remove prefix # from record separator, convert hex num to dec
        outputStr = outputStr""$0""sprintf("%c", decNum); # reconstruct output string
}
END {print outputStr}

Результат

echo %2fhome%40%21%23 |awk -f script.awk
/home@!#
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...