Как применить программу к столбцу в тексте в bash / awk? - PullRequest
0 голосов
/ 22 апреля 2020

У меня есть текст, который содержит что-то вроде этого:

column1 column2 column3 column4
text1.1 text1.2 text1.3 text1.4
text2.2 text2.2 text2.3 text3.4

Я хочу выполнить программу, которая преобразует весь текст в столбце 2 в новый текст. Программа принимает стандартный ввод и возвращает стандартный вывод, поэтому он называется так: echo "text-to-transform" | myprogram и возвращает "transformed-text" в стандартный вывод.

Какой самый простой способ применить myprogram к столбцу 2 и отобразить вывод в bash?

Вывод будет выглядеть примерно так

column1 column2 column3 column4
text1.1 transformed-text1.2 text1.3 text1.4
text2.2 transformed-text2.2 text2.3 text3.4

Я предполагаю, что awk - путь, но я не знаю достаточно об этом.

Спасибо

Ответы [ 3 ]

2 голосов
/ 23 апреля 2020
$ cat tst.awk
BEGIN { myprogram = "tr [:lower:] [:upper:]" }
NR>1 {
    cmd = "printf \047%s\n\047, \047" $2 "\047 | " myprogram
    if ( (cmd | getline line) > 0 ) {
        $2 = line
    }
    close(cmd)
}
{ print }

$ awk -f tst.awk file
column1 column2 column3 column4
text1.1 TEXT1.2 text1.3 text1.4
text2.2 TEXT2.2 text2.3 text3.4

Заменить myprogram = "tr [:lower:] [:upper:]" на myprogram = "<whatever your real program is called>". Вы даже можете параметризовать его, если хотите:

$ cat tst.awk
NR>1 {
    cmd = "printf \047%s\n\047, \047" $col "\047 | " myprogram
    if ( (cmd | getline line) > 0 ) {
        $col = line
    }
    close(cmd)
}
{ print }

$ awk -v myprogram='tr [:lower:] [:upper:]' -v col=2 -f tst.awk file
column1 column2 column3 column4
text1.1 TEXT1.2 text1.3 text1.4
text2.2 TEXT2.2 text2.3 text3.4

$ awk -v myprogram='wc -c' -v col=2 -f tst.awk file
column1 column2 column3 column4
text1.1        9 text1.3 text1.4
text2.2        9 text2.3 text3.4

$ awk -v myprogram="sed 's/x/X/' | tr 't' '#'" -v col=3 -f tst.awk file
column1 column2 column3 column4
text1.1 text1.2 #eX#1.3 text1.4
text2.2 text2.2 #eX#2.3 text3.4
1 голос
/ 22 апреля 2020

С помощью awk вы можете просто конкатенировать префикс ко второму полю, например,

awk 'FNR > 1 && NF > 1 {$2="transformed-"$2}1' file

, который просто проверяет, что у вас есть по крайней мере 2 поля в строке, а затем устанавливает, а затем конкатенирует префикс "transformed-" ко второму полю в строке от второй строки в файле до конца.

Пример использования / Вывод

Использование простого heredo c для ввода awk вы можете сделать:

$ cat << eof | awk 'FNR > 1 && NF > 1 {$2="transformed-"$2}1'
> column1 column2 column3 column4
> text1.1 text1.2 text1.3 text1.4
> text2.2 text2.2 text2.3 text3.4
> eof
column1 column2 column3 column4
text1.1 transformed-text1.2 text1.3 text1.4
text2.2 transformed-text2.2 text2.3 text3.4
1 голос
/ 22 апреля 2020

Вот ужасный способ, просто используя sed для простого преобразования в столбец 2:

paste <(cut -f1 -d' ' file) <(cut -f2 -d' ' file | sed 's/text/TEXT/') <(cut -f3,4 -d' ' file)

Вывод

text1.1 TEXT1.2 text1.3 text1.4
text2.2 TEXT2.2 text2.3 text3.4

Это по существу склеив 3 файла рядом друг с другом, поэтому прочитайте его следующим образом:

paste file1 file2 file3

где file1 - это то, что вы получаете, когда вы вырезаете первое поле из входного файла, file2 - это то, что вы получаете когда вы вырезаете и преобразуете второе поле входного файла, и file3 - это то, что вы получаете, когда вырезаете поля 3 и 4 из входного файла.


Или просто bash:

#!/bin/bash

while read c1 c2 rest ; do
     c2trans=$(echo "$c2" | ./transformer)
     echo "$c1 $c2trans $rest"
done < file
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...