我有一个如下所示的文件:
Marketing Ranjit Singh FULLEagles Dean Johnson
Marketing Ken Whillans FULLEagles Karen Thompson
Sales Peter RobertsonPARTGolden TigersRich Gardener
President Sandeep Jain CONTWimps Ken Whillans
Operations John Thompson PARTHawks Cher
Operations Cher CONTVegans Karen Patel
Sales John Jacobs FULLHawks Davinder Singh
Finance Dean Johnson FULLVegans Sandeep Jain
EngineeringKaren Thompson PARTVegans John Thompson
IT Rich Gardener FULLGolden TigersPeter Robertson
IT Karen Patel FULLWimps Ranjit Singh
我想使用 grep 命令在第二列中搜索“John”并搜索最后一列,但对于第二列中的每个“John”,我想要最后一列的输出。
最终结果应该是这样的:
John Thompson Cher
John Jacobs Davinder Singh
Dean Johnson Sandeep Jain
答案1
#! /bin/bash
while read line; do
if [[ ${line:11:15} =~ John ]]; then
echo " ${line:11:15} ${line:43}"
fi
done <file
答案2
grep
您可以通过从行开头匹配正确数量的字符来执行选择:
grep -E '^.{11,22}John'
John
必须在第 11-26 列的范围内开始和结束。
用空格替换某些列不在 grep 的能力范围内。使用 GNU grep,您可以-o
仅输出匹配的部分,但您将无法将两列与中间有额外的空格结合起来。
答案3
tab=$(printf '\t')
cut -c12-26 file | paste - file | grep "^[^$tab]*John" | cut -c1-16,60-
正如吉尔斯所说,你无法独自完成这件事grep
。grep
代表g/re/p
(ed/ex/vi
命令),即打印与 re 匹配的行。
答案4
让我们结合一下刚才展示的解决方案的一些提示。
来自斯蒂芬+吉尔斯:
grep -E '^.{11,22}John' source.txt | cut -c12-26,44-
# or, if you want only "John " and not Johnson, add a space after John.
grep -E '^.{11,22}John ' source.txt | cut -c12-26,44-
这里你还需要使用/bin/grep
and /bin/cut
。
来自吉尔斯+豪克:
grep -E '^.{11,22}John' source.txt | while read line; do echo "${line:11:14} ${line:43}"; done
这里你还需要使用/bin/grep
and echo
。在现代 shell 中你会发现echo
像内置命令所以它需要更少。
Hauke 的解决方案在安装程序方面成本较低:它只需要echo
(内置 so bash
),但甚至不需要/bin/grep
,如问题中所希望的那样。
更新我们来玩一会儿吧。
日常生活中我们跑步片段即时创建并可能永远不再使用的代码;花费并不总是方便我们人类的时代优化它或尝试不同的变化......但是塞梅尔在《疯狂的年月》中:另一方面,很有可能这是一个case-study question
,甚至可能是一个家庭作业不完全清楚。恕我直言,在这个光学器件中,所有不同的方法和解决方案都是有用的。
看来我们都同意,对于大量的行,使用已编译的程序比使用一系列 shell 命令更好(更快)。但什么是大呢?我认为数字(和图表)比文字更能表达想法:让我们看看。
这里的食谱:行数不断增加的一组文件,氮,做好了准备。每一行都是从此处发布的 11 行原文中随机提取的。
的价值观氮使用的是
11 22 55 110 220 550 1100 2200 5500 11000 110000 1100000 11000000
.
这片段测试的有:
- 这
Cut+Paste+Grep+Cut
tab=$(printf '\t') ; cut -c12-26 file | paste - file | grep "^[^$tab]*John" | cut -c1-16,60-
-绿色的 Only Grep
-蓝色grep -E '^.{11,22}John' source.txt
。只是grep
按照要求没有格式化输出。- 这
Grep+Cut
红色 [grep -E '^.{11,22}John' source.txt | cut -c12-26,44-
]。 - - Violet
Grep+While
[参见上面的答案,之前的 grep 和 while 循环]。 While loop
- 黄色一个完整的 bash 解决方案,不需要grep
对于每个文件大小和片段, 多次重复,NR代表,从 400(对于较短的文件)开始制作,并随着氮最后一个减至 100、10 和 1。
其值被记录为每行时间,总磷,又名即时的由内置函数测量
time
并取平均值NR代表和氮。既然两者总磷和氮跨越 10 的幂,绘制常用对数(以 10 为底,或 10 的幂)。报告的线是接触每个点的贝塞尔曲线。
对于较大的值氮这每行时间变得几乎恒定。这就是所谓的渐近行为。正如预期的那样,编译的程序使用的数量越少,结果就越快。
相反,对于小文件,结果相反。不同代码的效率在(对于我们的示例)40 到 140 行之间的区域中相互交叉。即使对于小文件来说确实很小,即使整体人类时间使用时,当需要处理大量小文件时,同样的考虑不再有效:纯 bash 代码(黄色)渐近地比绿色代码慢 8.12 倍,并且甚至慢了157倍对于红色文件(对于 11M 行文件,它使用 334.56 秒,而不是绿色的 41.21 秒和红色的 2.16 秒),对于 11 行文件,它分别快 2.16 倍和 1.58 倍,当它使用 1.20 秒进行 400 次重复时,而不是红色的 1.89 秒或绿色的 2.59 秒。
结论: 你知道的越多,你就越能挑战,并尽可能检查! :-)
Ps> 类似的考虑可以在用户时间和系统时间,但交叉区域略有不同。
巴什 4.3.11(1)-发布
粘贴(GNU coreutils)8.21
切 (GNU coreutils)8.21
grep (GNU grep)2.16
核心3.13.0-24-通用x86_64