如何对特定列的所有字段应用命令?

如何对特定列的所有字段应用命令?

我有一个命令cmd,它以一个字符串作为参数并返回另一个字符串。

我需要将此命令应用于 5x7 表格格式的文件的一个特定列(例如第 3 列),这样就不必

string11 string12 string13 string14 string15 string16 string17
string21 string22 string23 string24 string25 string26 string27
string31 string32 string33 string34 string35 string36 string37
string41 string42 string43 string44 string45 string46 string47
string51 string52 string53 string54 string55 string56 string57

我有

string11 string12 $(cmd string13) string14 string15 string16 string17
string21 string22 $(cmd string23) string24 string25 string26 string27
string31 string32 $(cmd string33) string34 string35 string36 string37
string41 string42 $(cmd string43) string44 string45 string46 string47
string51 string52 $(cmd string53) string54 string55 string56 string57

其中$(cmd string<i><j>)表示应用cmdstring<i><j>

如何将自定义命令cmd应用于表格格式的文件的任意列号?

PS:我更喜欢使用awk而不是sed

答案1

使用gawk(也可能使用nawk- 但据我所知不是使用mawk),您应该能够使用 形式来做到这"command" | getline variable一点getline

例如,使用以下脚本作为测试cmd,它接受单个字符串参数并输出其大写版本

#!/bin/sh

printf '%s' "$1" | sed 's/.*/\U&/'

然后将您的示例输入为file

$ gawk '{"./cmd "$3 | getline $3}1' file
string11 string12 STRING13 string14 string15 string16 string17
string21 string22 STRING23 string24 string25 string26 string27
string31 string32 STRING33 string34 string35 string36 string37
string41 string42 STRING43 string44 string45 string46 string47
string51 string52 STRING53 string54 string55 string56 string57

答案2

有一个不太为人所知的功能,sed它允许您执行命令。这是 GNU sed 的,调用方式如下/e

$ sed 's/1/echo 555/e' <<< "123"
55523

在我们的例子中,让我们捕获块并通过给定的方式处理它cmd

首先,正确捕捉群体:

$ sed -r 's/^((\w+\W+){2})\w+(.*)/printf "%s%s%s" "\1" "\2" "\3"/e' file
string11 string12 string12  string14 string15 string16 string17
string21 string22 string22  string24 string25 string26 string27
string31 string32 string32  string34 string35 string36 string37
string41 string42 string42  string44 string45 string46 string47
string51 string52 string52  string54 string55 string56 string57

这基本上捕获了整行并将其打印回来,printf并使用捕获的组作为参数。你现在发现这有点愚蠢,因为它只是打印回来。

由于您可以cmd针对给定的字符串执行操作,因此您应该使用:

sed -r 's/^((\w+\W+){2})\w+(.*)/printf "%s%s%s" "\1" "$(cmd "\2")" "\3"/e' file

cmdawk 'BEGIN {print 1}',那么我们会说:

$ sed -r 's/^((\w+\W+){2})\w+(.*)/printf "%s%s%s" "\1" "$(awk "BEGIN{print 1}")" "\3"/e' file
string11 string12 1 string14 string15 string16 string17
string21 string22 1 string24 string25 string26 string27
string31 string32 1 string34 string35 string36 string37
string41 string42 1 string44 string45 string46 string47
string51 string52 1 string54 string55 string56 string57

正如你所见,这里的想法是

所有这些都基于Sed 使用捕获组作为参数替换 bash 命令的输出我基于此创建如何在 sed 中更改日期格式?

相关内容