Не могли бы вы попробовать следующее:
#!/bin/bash
pat="(assign x to )([[:digit:]]+)( and y to )([[:digit:].]+)"
while IFS= read -r line; do
if [[ $line =~ $pat ]]; then
echo "#$line"
x2=$(echo "(${BASH_REMATCH[2]} + 1) / 2" | bc)
y2=$(echo "${BASH_REMATCH[4]} * 2" | bc)
echo "${BASH_REMATCH[1]}$x2${BASH_REMATCH[3]}$y2"
else
echo "$line"
fi
done < ifile.txt > ofile.txt
Вывод:
this is a text file
#assign x to 9 and y to 10.0702
assign x to 5 and y to 20.1404
define f(x)=x+y
- Регулярному выражению
(assign x to )([[:digit:]]+)( and y to )([[:digit:].]+)
соответствует буквенная строка, за которой следуют цифры, а затем буквенная строка, за которой следуют цифры, включая десятичную точку. - Команда
bc
(${BASH_REMATCH[2]} + 1) / 2
рассчитывает значение ceiling
ввода, деленное на 2. - Следующая команда
bc
${BASH_REMATCH[4]} * 2
умножает входные данные на 2.
Я выбрал bash
только потому, что он поддерживает back reference
в регулярных выражениях и его легче анализировать и повторно использовать входные параметры, чем awk
, Как часто указывалось, bash
не подходит для обработки больших файлов по причине производительности. Если вы планируете использовать большие / несколько файлов, рекомендуется использовать другие языки, такие как perl
.
С perl
вы можете сказать:
perl -pe 's|(assign x to )([0-9]+)( and y to )([0-9.]+)|
"#$&\n" . $1 . int(($2 + 1) / 2) . $3 . $4 * 2|ge' ifile.txt > ofile.txt
[РЕДАКТИРОВАТЬ ]
Если ваш ifile.txt выглядит следующим образом:
this is a text file
assign x to 9 and y to 10.0702 45
define f(x)=x+y
- Перед числами находится более одного пробела.
- Существует еще одно значение в конце (после пробелов).
Затем попробуйте следующее:
pat="(assign x to +)([[:digit:]]+)( and y to +)([[:digit:].]+)( +)([[:digit:].]+)"
while IFS= read -r line; do
if [[ $line =~ $pat ]]; then
echo "#$line"
x2=$(echo "(${BASH_REMATCH[2]} + 1) / 2" | bc)
y2=$(echo "${BASH_REMATCH[4]} * 2" | bc)
y3=$(echo "${BASH_REMATCH[6]} * 2" | bc)
echo "${BASH_REMATCH[1]}$x2${BASH_REMATCH[3]}$y2${BASH_REMATCH[5]}$y3"
else
echo "$line"
fi
done < ifile.txt > ofile.txt
Результат:
this is a text file
#assign x to 9 and y to 10.0702 45
assign x to 5 and y to 20.1404 90
define f(x)=x+y
Знак плюс после пробела является regex quantifier
и определяет количество повторений. В этом случае он соответствует одному или нескольким пробелам.