我有一条返回输出的命令:
$ show
file 1 banana
file 3 apple
file 2 watermelon
file 0 tomato
file name 0=abc 1=def
2=ghi 3=jkl
使用给定的文件名,我想找到相关的单词。例如,ghi
将匹配watermelon
。
我能够将文件号与sed
匹配并重新使用结果:
$ filenum=$(show | sed -n 's/.*\<\([0-9]*\)=ghi\>.*/\1/p')
$ show | sed -n 's/file '"$filenum"' \([a-z]*\)/\1/p'
watermelon
show
的输出计算起来可能很长,所以我想避免两次调用它。也可以将输出存储在变量中并执行相同的操作:
$ out=$(show)
$ filenum=$(echo "$out" | sed -n 's/.*\<\([0-9]*\)=ghi\>.*/\1/p')
$ echo "$out" | sed -n 's/file '"$filenum"' \([a-z]*\)/\1/p'
watermelon
但是我想用最少的命令来做到这一点。
仅通过一次调用sed
,awk
或任何类似的工具,是否有可能达到相同的结果?
EDIT 我想要一个命令magic-command
,对于给定的文件名,该命令将在show
命令的输出中打印相关的单词。例如:
$ show | magic-command "ghi"
watermelon
$ show | magic-command "abc"
tomato
$ show | magic-command "def"
banana
show
命令的格式如下:
file <filenum> <word>
...
file name <filenum>=<filename> ...
编辑2
感谢您的回答,我之前从未使用过awk
,所以我对您有所收获!所以我修补了它们,并得到以下结果:
$ cat magic-command.sh
#!/bin/sh
awk '
# Match the `<filenum>=<filename>` using the given <filename>
# to find to <filenum>
match($0, /([0-9]*)='"$1"'/, out ) {
filenum=out[1]
}
# Fill n2name using the `file <filenume> <word>` lines
/\<file [0-9]*\>/ {
n2name[$2]=$3
}
END {
print n2name[filenum]
}'
然后:
$ show | ./magic-command.sh "ghi"
watermelon
答案 0 :(得分:1)
编辑: :按照OP添加解决方案,OP需要将其与另一个程序一起运行,然后尝试执行以下操作。
cat script.ksh
your_command | awk -v command="$1" -F' +|=' '
/^file/ && !/^file name/{
a[$2]=$NF
}
/^file name/{
for(i=3;i<=NF;i+=2){
array[$i]=$(i+1)}
}
/^ +/{
for(j=2;j<=NF;j+=2){
array[$j]=$(j+1)}
}
END{
for(i in array){
if(array[i]==command){ print array[i],a[i] }
}}'
以下将是我们运行脚本时的输出。
./script.ksh "ghi"
ghi watermelon
您的帖子中仍然存在很多不清楚的问题,完全基于您所发布的内容,请尝试一次(仅根据示例中的完整显示)。
awk -F' +|=' '
FNR==NR{
if($0 ~ /file name/){
for(i=3;i<=NF;i+=2){
array[$i]=$(i+1)
}
getline
for(j=2;j<=NF;j+=2){
array[$j]=$(j+1)
}
}
next
}
($2 in array){
print array[$2],$NF
}' Input_file Input_file
输出如下。
def banana
jkl apple
ghi watermelon
abc tomato
ghi jkl
考虑到您的show
函数在这里输出到Input_file
中,我在这里读取Input_file 2次。
答案 1 :(得分:1)
$ cat tst.awk
/=/ {
for (i=1; i<=NF; i++) {
if ( split($i,f,/=/) == 2 ) {
name2nr[f[2]] = f[1]
}
}
next
}
{ nr2text[$2] = $3 }
END { print nr2text[name2nr[name]] }
使用cat file
(其中file
包含问题中提供的show
的输出)代替show
:
$ cat file | awk -v name='ghi' -f tst.awk
watermelon
如果文件名可以包含=
或空格,则以上内容(以及其他当前发布的答案和任何其他明显的解决方案)将失败。如果可能发生,那么您需要告诉我们如何识别文件名,而不是字段和/或赋值语句。