Приложение Packaging Go для Debian

В качестве альтернативы итерации по 0 .. ${#string}-1 с циклом for / while есть два других способа, с которыми я могу думать: только bash : используя =~ и используя printf ]. (Существует третья возможность использования выражения eval и {..} последовательности, но это не имеет ясности.)

С правильной средой и поддержкой NLS в bash они будут работать с не-ASCII, как можно надеяться, удаляя потенциальные источники сбоев со старыми системными инструментами, такими как sed, если это вызывает беспокойство.

Используя =~ и регулярные выражения, преобразуя строку в массив в одном выражении:

string="wonkabars"
[[ "$string" =~ ${string//?/(.)} ]]       # splits into array
printf "%s\n" "${BASH_REMATCH[@]:1}"      # loop free: reuse fmtstr
declare -a arr=( "${BASH_REMATCH[@]:1}" ) # copy array for later

Способ это работает, чтобы выполнить расширение string, которое заменяет каждый отдельный символ для (.), а затем сопоставляет это сгенерированное регулярное выражение с группировкой для захвата каждого отдельного символа в BASH_REMATCH[]. Индекс 0 установлен на всю строку, так как этот специальный массив доступен только для чтения, вы не можете его удалить, обратите внимание на :1, когда массив расширен, чтобы пропустить индекс 0, если это необходимо. Некоторые быстрые тесты для нетривиальных строк (> 64 символа) показывают, что этот метод существенно быстрее, чем один, используя операции bash и операции с массивом.

Вышеупомянутое будет работать со строками, содержащими строки новой строки , =~ поддерживает POSIX ERE, где . по умолчанию совпадает с чем-либо, кроме NUL , то есть регулярное выражение скомпилировано без REG_NEWLINE. (Поведение POSIX-обработки текста утилит по умолчанию по-разному отличается и обычно является.)

Вторая опция, используя printf:

string="wonkabars"
ii=0
while printf "%s%n" "${string:ii++:1}" xx; do 
  ((xx)) && printf "\n" || break
done 

Этот цикл увеличивает индекс ii для печати одного символа за раз и разрывается, когда символов нет. Это было бы еще проще, если bash printf вернул количество символов, напечатанных (как на C), а не статус ошибки, вместо этого количество напечатанных символов будет записано в xx с помощью %n. (Это работает как минимум до bash-2.05b.)

С bash-3.1 и printf -v var у вас немного больше гибкости и вы можете избежать падения с конца строки, если вы будете делать что-то, кроме печати символов, например для создания массива:

declare -a arr
ii=0
while printf -v cc "%s%n" "${string:(ii++):1}" xx; do 
    ((xx)) && arr+=("$cc") || break
done

37
задан John Weldon 5 April 2016 в 22:30
поделиться