части шаблона sed в качестве входных данных для других функций bash - PullRequest
0 голосов
/ 16 января 2019

Я пытаюсь заменить числа с плавающей точкой, такие как 1.2e + 3, на их целочисленное значение 1200. Для этого я использую sed следующим образом:

 echo '"1.2e+04"' | sed "s/\"\([0-9]\+\.[0-9]\+\)e+\([0-9]\+\)\"/$(echo \1*10^\2|bc -l)/"

, но части шаблона \1 и \2 не обрабатываются в эхо.

Есть ли способ решить эту проблему с помощью sed? Заранее спасибо

Ответы [ 4 ]

0 голосов
/ 16 января 2019

Лучший способ решить проблему правильно - использовать расширенную комбинацию решений @ tshiono и @ Romeo:

sed "s/\(.*\)\([0-9]\+\.[0-9]\+e+[0-9]\+\)\(.*\)/printf '\1'\; echo \2 |awk '{printf \"%d\",\$0}'\;printf '\3'\;/e"

Таким образом, можно преобразовать все такие числа с плавающей точкой в ​​произвольные контексты.

например:

echo '"1.2e+04"' | sed "s/\(.*\)\([0-9]\+\.[0-9]\+e+[0-9]\+\)\(.*\)/printf '\1'\; echo \2 |awk '{printf \"%d\",\$0}'\;printf '\3'\;/e"

выходы

"12000"

и

echo 'abc"1.2e+04"def' | sed "s/\(.*\)\([0-9]\+\.[0-9]\+e+[0-9]\+\)\(.*\)/printf '\1'\; echo \2 |awk '{printf \"%d\",\$0}'\;printf '\3'\;/e"

выходы

abc"12000"def
0 голосов
/ 16 января 2019

Если вас устраивает команда awk, подобная этой, может выполнить работу:

echo 1.2e+4|awk '{printf "%d",$0}'
0 голосов
/ 16 января 2019

В двойных кавычках \1 и \2 интерпретируются как буквальные 1 и 2.Вам нужно добавить дополнительные обратные слеши, чтобы избежать их.Кроме того, замена $(command substitution) в sed, по-видимому, не работает, когда объединяется с обратными ссылками.Если вы используете GNU sed, вы можете вместо этого сказать что-то вроде:

echo '"1.2e+04"' | sed "s/\"\([0-9]\+\.[0-9]\+\)e+\([0-9]\+\)\"/echo \"\\1*10^\\2\"|bc -l/;e"

, что дает:

12000.0

Если вы хотите отрубить десятичную точку, вы будете знать,что делать; -).

0 голосов
/ 16 января 2019

Возможно, лучше использовать perl (или другой типизированный язык) для управления типами переменных:

echo '"1.2e+04"' | perl -lane 'my $a=$_;$a=~ s/"//g;print sprintf("%.10g",$a);print $a;'

В любом случае, ваше sed выражение неверно, оно должно быть:

echo '"1.2e+04"' | sed "s/\"\([0-9]\+\.[0-9]\+\)e+\([0-9]\+\)\"/$(echo \1*10^\3 + \2*10^$(echo \3 - 1 | bc -l)|bc -l)/"

...