Как назначить совпадение моего регулярного выражения переменной?
У меня есть текстовый файл с различными записями. Каждая запись заканчивается строкой, содержащей все звездочки.
Я хотел бы использовать команды оболочки для синтаксического анализа этого файла и назначения каждой записи переменной. Как я могу это сделать?
Вот пример входного файла:
***********
Field1
***********
Lorem ipsum
Data to match
***********
More data
Still more data
***********
Вот как выглядит мое решение до сих пор:
#!/bin/bash
for error in `python example.py | sed -n '/.*/,/^\**$/p'`
do
echo -e $error
echo -e "\n"
done
Однако это просто присваивает каждому слову в согласованном тексте значение $error, а не целый блок.
Ответы
Ответ 1
Я удивлен, увидев здесь не родное решение bash. Да, bash имеет регулярные выражения. Вы можете найти множество случайных документов онлайн, особенно если вы включили "bash_rematch" в свой запрос или просто просмотрите страницы руководства. Здесь глупый пример, взятый из здесь и слегка измененный, который печатает весь матч и каждое из захваченных совпадений для регулярного выражения.
if [[ $str =~ $regex ]]; then
echo "$str matches"
echo "matching substring: ${BASH_REMATCH[0]}"
i=1
n=${#BASH_REMATCH[*]}
while [[ $i -lt $n ]]
do
echo " capture[$i]: ${BASH_REMATCH[$i]}"
let i++
done
else
echo "$str does not match"
fi
Важным битом является то, что расширенный тест [[ ... ]]
с использованием его сравнения regex =~
сохраняет все совпадения в ${BASH_REMATCH[0]}
, а зафиксированные совпадения - в ${BASH_REMATCH[i]}
.
Ответ 2
Если вы хотите сделать это в Bash, вы можете сделать что-то вроде следующего. Он использует globbing вместо регулярных выражений (опция extglob
shell позволяет расширенное сопоставление шаблонов, так что мы можем сопоставить строку, состоящую только из звездочек.)
#!/bin/bash
shopt -s extglob
entry=""
while read line
do
case $line in
+(\*))
# do something with $entry here
entry=""
;;
*)
entry="$entry$line
"
;;
esac
done
Ответ 3
Попробуйте добавить двойные кавычки вокруг команды.
#!/bin/bash
for error in "`python example.py | sed -n '/.*/,/^\**$/p'`"
do
echo -e $error
echo -e "\n"
done
Ответ 4
в зависимости от того, что вы хотите делать с переменными
awk '
f && /\*/{print "variable:"s;f=0}
/\*/{ f=1 ;s="";next}
f{
s=s" "$0
}' file
выход:
# ./test.sh
variable: Field1
variable: Lorem ipsum Data to match
variable: More data Still more data
приведенное выше просто распечатывает их. если вы хотите, сохраните в массиве для последующего использования... например, array [++ d] = s
Ответ 5
Разделение записей в (ba) sh не так просто, но может быть сделано с использованием IFS для разделения на отдельные символы (просто установите IFS = '*' перед циклом for, но это создает несколько пустых записей и является проблематичным, если есть запись содержит "*" ). Очевидным решением является использование perl или awk и использование RS для разделения ваших записей, поскольку эти инструменты предоставляют лучшие механизмы для разделения записей. Гибридное решение состоит в том, чтобы использовать perl для разделения записей и использовать perl функцию bash с нужной записью. Например:
#!/bin/bash
foo() {
echo record start:
echo "[email protected]"
echo record end
}
export -f foo
perl -e "$/='********'; while(<>){chomp;system( \"foo '\$_'\" )}" << 'EOF'
this is a 2-line
record
********
the 2nd record
is 3 lines
long
********
a 3rd * record
EOF
Это дает следующий результат:
record start:
this is a 2-line
record
record end
record start:
the 2nd record
is 3 lines
long
record end
record start:
a 3rd * record
record end