заполнить массив всеми вхождениями шаблона
Сначала преобразуйте ваш файл, чтобы получить значимый разделитель, напр.нулевой байт, с отл.GNU sed с переключателем -z
:
sed -z 's/"\([^"]*\)"[^"]*/\1\00/g'
Я добавил [^"]*
в конце, чтобы символы, не находящиеся между "
, были удалены.
После этого он становитсяболее тривиально разобрать это.
Вы можете получить первый элемент с помощью:
head -z -n1
Или отсортировать и посчитать вхождения:
sort -z | uniq -z -c
Или загрузить в массив с помощью bash's maparray
:
maparray -d '' -t arr < <(<input sed -z 's/"\([^"]*\)"[^"]*/\1\00/'g))
В качестве альтернативы вы можете использовать ex.$'\01'
в качестве разделителя, пока он уникален, становится просто анализировать такие данные в bash.
Обработка таких потоков довольно сложна в bash.Вы не можете установить значение переменной в оболочке со встроенным нулевым байтом.Также ожидайте иногда предупреждения о подстановках команд.Обычно при обработке данных с произвольными байтами я конвертирую их с xxd -p
в обычный ascii и обратно с xxd -r -p
.С этим становится проще.
Будет выведен следующий скрипт:
cat <<'EOF' >input
"My name
is XXX"
"My name is YYY"
"Today
is
the "
EOF
sed -z 's/"\([^"]*\)"[^"]*/\1\x00/g' input > input_parsed
echo "##First element is:"
printf '"'
<input_parsed head -z -n1
printf '"\n'
echo "##Elemets count are:"
<input_parsed sort -z | uniq -z -c
echo
echo "##The array is:"
mapfile -d '' -t arr <input_parsed
declare -p arr
(форматирование немного отключено из-за не разделенного на новую строку вывода из uniq
):
##First element is:
"My name
is XXX"
##Elemets count are:
1 My name
is XXX 1 My name is YYY 1 Today
is
the
##The array is:
declare -a arr=([0]=$'My name\nis XXX' [1]="My name is YYY" [2]=$'Today\nis\nthe ')
Проверено на repl.it .