我想grep一个单词,然后找到该行中的第二列,并检查它是否大于一个值。是的,我想打印上一行。
例如:
输入文件
AAAAAAAAAAAAA
BB 2
CCCCCCCCCCCCC
BB 0.1
输出
AAAAAAAAAAAAA
现在,我想搜索BB,如果该行中的第二列(2或0.1)大于1,我想打印上一行。
有人可以用grep和awk帮我吗?谢谢。任何其他建议也欢迎。感谢。
答案 0 :(得分:16)
这可以是一种方式:
$ awk '$1=="BB" && $2>1 {print f} {f=$1}' file
AAAAAAAAAAAAA
$1=="BB" && $2>1 {print f}
如果第一个字段正好是BB
且第二个字段大于1
,则打印f
,即存储值。{f=$1}
将当前行存储在f
中,以便在阅读下一行时可以访问该行。答案 1 :(得分:4)
另一种选择:如果条件匹配,则反转文件并打印下一行行:
tac file | awk '$1 == "BB" && $2 > 1 {getline; print}' | tac
答案 2 :(得分:1)
我认为需要提及的是,此类问题的最通用解决方案涉及两个步骤:
在中间文件中,某些十进制数字序列后跟一个分隔符(出于人为原因,通常是添加了制表符或空格)被解析(相对于概念文件而言是带外的),相对于基线文件而言是带外的。
即使仅限于命令行,确保中间文件从不击中磁盘也很容易。您只需要使用支持过程替换的高级外壳程序,例如ZSH(我自己的最爱):
paste <( <input.txt awk "BEGIN { R=0; N=0; } /Header pattern/ { N=1; } { R=R+N; N=0; print R; }" ) input.txt | awk -f yourscript.awk
让我们展示一种更适合展示的方式:
P="/Header pattern/"
X="BEGIN { R=0; N=0; } $P { N=1; } { R=R+N; N=0; print R; }"
paste <( <input.txt awk $X ) input.txt | awk -f yourscript.awk
这将启动三个过程:简单的内联AWK脚本paste
,以及您真正想首先运行的AWK脚本。
在幕后,<()
命令行结构创建一个命名管道,并将要粘贴的管道名称作为其第一个输入文件的名称传递。对于paste
的第二个输入文件,我们将其命名为原始输入文件的名称(因此,该文件由两个不同的进程依次并行读取,这两个进程之间最多使用一个< / strong>从磁盘读取(如果输入文件很冷)。
中间名为魔术的管道是一个内存中的FIFO,古代Unix可能以平均大小约16 kB进行管理(如果paste
进程耗时缓慢,则间歇地暂停yourscript.awk
进程此FIFO向下)。
也许现代的Unix可以在其中投入更大的缓冲区,但这肯定不是您应该关注的稀缺资源,直到您编写第一个 truly 高级命令行并进行涉及这些进程的重定向成千上万:-)
在现代CPU上,所有这三个进程都可以轻松地发现自己在单独的内核上运行。
这些过程中的前两个过程确实很琐碎:一个具有单个模式匹配和一些次要簿记的AWK脚本,并粘贴带有两个参数的调用。 yourscript.awk
的运行速度将比这些更快。
什么,您的开发机器没有轻松加载的内核来在执行域中几乎免费提供此主shell-master解决方案模式?
响,响。
你好?
嘿,这是给你的。 2018年刚刚来临,并希望解决问题。
2020年正式成为MTV的死因:这就是我们喜欢的方式,一无所有的魔力管道和免费的核心。不要大声说出最近正在摇摇欲坠的任何特定TLA芯片供应商。
作为最终的性能考虑,如果您不希望解析实际记录号的开销:
X="BEGIN { N=0; } $P { N=1; } { print N; N=0; }"
现在,在in-FIFO中间文件中,每行仅附加两个字符(“ 0”或“ 1”,并由paste
添加默认分隔符),其中“ 1”首先标记记录中的行。
在后台,这些与您编写任何常规管道命令时Unix实例化的魔术FIFO没什么不同:
cat file | proc1 | proc2 | proc2
三个未命名的管道(甚至不需要使用专门用于cat
的整个过程)。
几乎不幸的是,由shell预先管理的默认stdin / stdout流的真正 exception 便利性掩盖了paste $magictemppipe1 $magictemppipe2
在99年没有值得考虑的其他性能考量的现实。在所有情况下所占的百分比。
“使用<()
Y型关节,卢克。”
您对问题域中自然语义分解的本能反射将极大地受益。
如果首先有人愿意将壳结构<()
命名为YODA运算符,我怀疑它至少在坚实的十年前就已被推向通用服务。
答案 3 :(得分:0)
结合sed和awk,您将获得以下信息:
sed 'N;s/\n/ /' < file |awk '$3>1{print $1}'
sed 'N;s/\n/ /
:合并第一行和第二行,并用空格替换下一行字符
awk '$3>1{print $1}'
:如果$ 3(第3列的值大于1)则打印$ 1(第1列)