Обработка строк с помощью фигурных скобок в bash

Сawk:

awk '{ printf("%.3g %.3g\n", $1, $2) }' file

При заданных данных получается

0.993 0.00704
0.646 0.354
0.993 0.00704
0.993 0.00704
0.993 0.00704
0.993 0.00704
0.993 0.00704
0.993 0.00704
0.5 0.5

Обратите внимание, что 0,00704 имеет пять десятичных знаков, но три значащих цифры.

Если вы хотите ровно три десятичных знака, используйте %.3fвместо %.3gи получите

0.993 0.007
0.646 0.354
0.993 0.007
0.993 0.007
0.993 0.007
0.993 0.007
0.993 0.007
0.993 0.007
0.500 0.500

Приведенные выше два варианта могут быть обобщены для переменного количества столбцов с использованием GNUawk:

awk -v CONVFMT='%.3g' '{ for (i=1; i<=NF; ++i) $i+=0; print }' file

Цикл с $i+=0заставляет awkповторно -форматировать значение каждого поля как число с плавающей запятой, что он будет делать, принимая во внимание CONVFMT(, что он будет более или менее делать эквивалент$i=sprintf(CONVFMT, $i)).


Если вы хотите вырезать цифры:

awk '{ for (i=1; i<=NF; ++i) $i=sprintf("%.5s", $i); print }' file

Это обрабатывает числа как строки и обрезает их после пяти символов (, что предполагает, что все числа меньше 10 и больше нуля ), генерируя

0.992 0.007
0.646 0.353
0.992 0.007
0.992 0.007
0.992 0.007
0.992 0.007
0.992 0.007
0.992 0.007
0.5 0.5

Для более общего сокращения чисел:

awk '{ for (i=1; i<=NF; ++i) if (match($i,".*\\.[0-9]?[0-9]?[0-9]?")) $i=substr($i,RSTART,RLENGTH); print }' file

Операция в цикле обрезает числа в точке, в которой заканчивается совпадение данного регулярного выражения (, если оно соответствует ).

1
06.04.2020, 13:24
2 ответа

Я бы не стал делать это в оболочке. Просто проанализируйте вывод grepперед сохранением в переменной :

.
title=$(grep -F '\title' file.tex | sed s'/.*{\(.*\)}/\1/')

или

title=$(grep -F '\title' file.tex | awk -F'[{}]' '{print $2}')

Или, если у вас есть GNU grepили любая другая реализация, поддерживающая -oи -P, вы можете сделать:

title=$(grep -oP '\\title\{\K[^}]+' file.tex)
0
28.04.2021, 23:18

Предполагая, что $titleявляется строкой\title{This is the title}:

title=${title#*{}
title=${title%\}}

{в подстановке первого параметра не нужно экранировать (экранирование не заставит его не работать, хотя ), но }во втором нужно экранировать. В первом вам дополнительно нужно *для соответствия биту \titleв строке, в качестве альтернативы используйте ${title#\\title{}для удаления явной строки \title{.

Кажется, вы перепутали %и #в своем коде и забыли *в подстановке, которая удаляет строку префикса.


Предполагая, что ни одна строка заголовка не занимает более одной строки, вы можете получить все эти строки из документа с помощью

sed -n 's/.*\\title{\([^}]*\)}.*/\1/p' file

Это соответствует (первому)\title{SOMETHING}в каждой строке и заменяет всю строку подстрокой SOMETHING. Все остальные данные отбрасываются.

1
28.04.2021, 23:18

Теги

Похожие вопросы