![如何对特定列的所有字段应用命令?](https://linux22.com/image/996159/%E5%A6%82%E4%BD%95%E5%AF%B9%E7%89%B9%E5%AE%9A%E5%88%97%E7%9A%84%E6%89%80%E6%9C%89%E5%AD%97%E6%AE%B5%E5%BA%94%E7%94%A8%E5%91%BD%E4%BB%A4%EF%BC%9F.png)
我有一个命令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>)
表示应用cmd
到string<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
说cmd
是awk '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 中更改日期格式?。