Bash: разделить по разделителю, но сохранить разделитель

Я хотел бы разделить строку на массив с помощью разделителей и сохранить эти разделители. Я пытался использовать IFS, но он не поддерживает разделители.

Например:

ligne="this.is/just(an]example"
IFS='}|//|)|(| |{|[|]|.|;|/"|,' read -ra ADDR <<< "$ligne"
for i in "${ADDR[@]}"; do
   echo $i
done

Я хочу, чтобы результат был таким:

this
.
is
/
just
(
an
]
example

Спасибо за вашу помощь!


person M. Ebner    schedule 21.09.2018    source источник
comment
bash на самом деле не предназначен для такого уровня обработки данных; любые функции, которые он имеет, обычно предназначены для простых манипуляций с именами файлов.   -  person chepner    schedule 21.09.2018


Ответы (2)


Вы можете использовать grep с опцией -o:

grep -oE '[^][^./(){};:,"]+|[][^./(){};:,"]' <<< "$ligne"

this
.
is
/
just
(
an
]
example

Regex in use is alternation based with 2 alternations:

  • [^][^./(){};:,"]+: Соответствует 1+ любому персонажу, который не принадлежит к классу персонажей.
  • |: OR
  • [][^./(){};:,"]: соответствует любому символу из класса символов.
person anubhava    schedule 21.09.2018
comment
OP может захотеть удалить + из второго чередования, пустые поля часто представлены последовательными разделителями, и в этом случае было бы лучше сопоставить каждый разделитель как отдельное вхождение, а не перегруппировать их. В качестве примечания я очень удивлен, что ваши классы персонажей не нарушены неэкранированным ]. Это потому, что ни [], ни [^] не будут допустимыми классами символов? - person Aaron; 21.09.2018
comment
@Aaron Если вы хотите, чтобы ] в выражении в квадратных скобках было первым символом, которому необязательно должен предшествовать ^ для инвертированного класса. - person Benjamin W.; 21.09.2018
comment
@Aaron: Хороший момент, чтобы не использовать квантификатор + для 2-го чередования (отредактировано). - person anubhava; 21.09.2018

Насколько мне известно, нет тривиального решения для встроенных функций Bash, но если это то, что вам нужно, вы можете сделать что-то вроде этого.

ligne="this.is/just(an]example"
array=()
while true; do
    for delim in '}' '//' ')' '(' ' ' '{' '[' ']' '.' ';' '/"' ','; do
        frag=${ligne#*"$delim"}
        [ "$frag" = "$ligne" ] || break
    done
    [ "$frag = "$ligne" ] && break
    head=${ligne%"$frag"}
    array+=("${head%"$delim"}" "$delim")
    ligne=$frag
done
person tripleee    schedule 21.09.2018