将文件的最后一行捕获为整数变量并在 awk 命令中使用

capture last line of file as integer variable and use in awk command

我正在尝试捕获文件的最后一行作为 awk 命令中使用的变量。

这是文件的示例(文件结尾):

cat file.txt 
....
 phylum:Chlorophyta 1
 phylum:Mucoromycota 1
column 6:
 superkingdom:Eukaryota 99
column 7:
 
 99

我想在 awk 命令中使用那个“99”作为整数,将其保存为变量,

tail -n1 file.txt
99 

例如

div=$(tail -n1 file.txt)

echo $div
99

用于第二个文件 (conf.txt),用于划分第二个字段中的数字:

cat conf.txt
Class 88
Family 78
Genus 44
Species 23

但是,当我尝试在 awk 命令中使用 $div 变量时(使用 -v 标志,如此处和其他地方在获取变量时使用 awk 所建议的),我收到此错误:

awk -v a=$div '{print /a}' conf.txt 
awk: can't open file {print /a}
 source line number 1


但是当 99 只是在 cmd 行上作为一个变量时,它工作得很好:

num=99
awk -v a=$num '{print /a}' conf.txt 
0.888889
0.787879
0.444444
0.232323

tail -1 的捕获中是否有额外的 spaces/characters?我遗漏了一些简单但基本的东西。

最后,我什至不想先保存为一个单独的变量如果我不需要,相反,只需捕获最后的行号 (99) 并直接放入 awk cmd,例如:

awk  '{print /[tail -1 file.txt]}' conf.txt 

这是伪代码(在括号中)...但是,这最终将是我想要的...

感谢您的帮助!

最后一行开头有一个space,所以命令变成

awk -v a= 99 '{print /a}' conf.txt

这是将 a 设置为空字符串,将 99 视为 awk 脚本,将其余部分视为文件名。

$div 中删除 space。

div=${div// /}

在 shell.

中使用引号作为一种习惯

鉴于:

cat file
blah blah
   99

命令 n=$(tail -n1 file) 在 99:

前面生成前导 spaces
n=$(tail -n1 file)
printf "\"%s\"\n" "$n"
"   99"

当你 认为 你正在检查没有引号的 $n 的值时,它尤其是一个 bug,因为领先的 spaces 被删除shell 在调用 echo.

之前

考虑:

echo $n         # no quotes - leading spaces stripped
99
echo "$n"       # preserve whitespace...
   99

现在,如果您尝试将不带引号的参数传递给 awk,space 对 shell 有意义并搞砸命令的解释方式:

awk -v n=$n 'BEGIN{printf "\"%s\", %s\n", n, n+1}'
awk: fatal: cannot open file `BEGIN{printf "\"%s\", %s\n", n, n+1}' for reading: No such file or directory

对比:

awk -v n="$n" 'BEGIN{printf "\"%s\", %s\n", n, n+1}'
"   99", 100

如果你想用awk代替tail的使用,你可以使用FNR==NR的习语来测试文件是否是第一个文件和==+0测试 awk 是否将其视为数字:

awk 'FNR==NR {n=+0== ? +0 : n; next} # n ends up being the last number seen
==+0{print /n}
' file conf.txt
0.888889
0.787879
0.444444
0.232323
 

启用调试模式和运行 awk 命令:

$ set -x
$ awk -v a=$div '{print /a}' conf.txt
+ awk -v a= 99 '{print /a}'
awk: fatal: cannot open file `{print /a}' for reading: No such file or directory

感兴趣:

  • -v a= - 定义 awk 变量 a 为空
  • 99 - awk code/script
  • '{print /a}' - 传递给 awk 脚本的第一个文件,以及错误消息的来源

正如其他人所指出的,您可以通过将 $div 括在双引号中来解决该错误:

$ awk -v a="$div" '{print /a}' conf.txt
+ awk -v 'a=  99' '{print /a}' conf.txt
0.888889
0.787879
0.444444
0.232323

感兴趣:

  • -v '= 99' - 定义 awk 变量 a 和字符串 ' 99'
  • 在这种情况下,当变量的其余部分可以解释为数字时,awk 忽略空格
  • '{print /a}' - awk code/script
  • conf.txt - 文件传递​​给 awk 脚本

Barmar 和 dawg 分别解决了从 div 中剥离空白并在整个过程中使用 awk 的问题。

而不是让 shell 调用一些命令来获取 file.txt 的最后一行,然后将其保存在 shell 变量中,然后将 awk 变量设置为从中填充的相同值shell 变量并将其传递给 awk,只需调用一次 awk:

$ awk 'NR==FNR{n=; next} {print /n}' file.txt conf.txt
0.888889
0.787879
0.444444
0.232323