Я согласен, что sed
не подходит. Будучи старомодным (или, может быть, просто немодным), я бы использовал Perl:
$ cat data
src/main.tsx(2,31): error TS2304: Cannot find name 'foo'.
$ perl -p -e 's/^(.*?)\((\d+),(\d+)\): (\w+) /sprintf("%s:%d:%d: %s: ", $1, $2-1, $3-1, $4)/e' data
src/main.tsx:1:30: error: TS2304: Cannot find name 'foo'.
$
Регулярное выражение лениво сопоставляет все до «(nn,mmm):
», за которым следует «слово», захватывая два цифры и то, что предшествует скобкам и слову. Затем он использует модификатор /e
(«оценивать правую сторону как выражение» - см. Операторы, подобные цитате Regexp ), чтобы выполнять вычитания, используя sprintf()
для форматирования информации. «Слово» будет захватывать error
или warning
или что-либо еще, все буквы, за которыми следует пробел. Вы можете использовать \S+
вместо \w+
для захвата любой последовательности непробельных символов. Я предполагаю, что разделители представляют собой одинарные пробелы; Вы можете использовать \s+
вместо пробелов, если это необходимо, чтобы соответствовать любой непустой последовательности пробелов. (Параметр -p
просто означает «чтение строк из именованных файлов или стандартный ввод, если файлы не названы, выполните действия в -e '…script…'
и напечатайте результат.)
Протестировано с 5.18.4 ( /usr/bin/perl
в macOS Mojave 10.14.6) и 5.30.0.
Если у вас есть процесс, выдающий ошибки, то вам нужно убедиться, что ошибки отправляются в сценарий Perl - это Сценарии оболочки, а не что-либо еще.
tsc 2>&1 |
perl -p -e 's/^(.*?)\((\d+),(\d+)\): (\w+) /sprintf("%s:%d:%d: %s: ", $1, $2-1, $3-1, $4)/e'
Если вам нужен стандартный вывод команды (tsc
в измененном вопросе и фрагменте сценария оболочки выше) в go где-то еще, тогда вам нужно быть осторожным (см. также Как передать в поток stderr, а не в stdout ), но возможно:
tsc 2>&1 >tsc.out |
perl -p -e 's/^(.*?)\((\d+),(\d+)\): (\w+) /sprintf("%s:%d:%d: %s: ", $1, $2-1, $3-1, $4)/e'
Канал изначально устанавливает стандартный вывод, идущий в Perl; 2>&1
отправляет туда и стандартную ошибку; >tsc.out
изменяет стандартный вывод, поэтому он переходит в файл tsc.out
, оставляя стандартную ошибку при переходе к каналу.