- 用于搜索字符串的参数
- 使用消隐不可搜索记录的方法(最简洁且可能最快)
-
index() 用于字符串的精确匹配
awk -v p='_RS1c80952b46129fc3bbf7b6d35e52f581d5d96edf' '
$1 == "SCR" {
f=$6
$1=$2=$3=$4=$5=$6=""
if (index($0, p))
print f
}
' inputfile.txt
只要前导分隔符不是搜索字符串的一部分......我们应该很高兴。
如果我们希望将此脚本格式化为适合一行:
awk -v p='_RS1c80952b46129fc3bbf7b6d35e52f581d5d96edf' '$1 == "SCR" { f=$6; $1=$2=$3=$4=$5=$6=""; if (index($0, p)) print f }' inputfile.txt
我决定今天用这个小脚本找点乐子……这是一个填充了副作用的函数变体,它最大限度地减少了全局变量的使用。建议前面的解决方案更简单(也是我们想要的),但是下面的代码既有趣又有教育意义:
awk -v p='_RS1c80952b46129fc3bbf7b6d35e52f581d5d96edf' '
function x(v, f, i) {
f=$6
$1=$2=$3=$4=$5=$6=""
i = index($0, v)
$0=f
return i
}
$1 == "SCR" && x(p)
' inputfile.txt
如何解决上述问题:
- 在 awk 中,我们可以传递比我们在函数定义中指定的更少的参数——函数中未使用的参数基本上是临时变量...您友好的 awk-ers使用 4 空间偏移的约定来标识临时变量。
- 我们使用与以前基本相同的算法,但不是在成功时使用
print f,而是很可爱,只需将f 放回行缓冲区。
- 那么,
print 在哪里???好吧,脚本的最后一行是我们放置 magic...模式成功是到print 行缓冲区。成功! :)
- 最后一点是关于最后一条语句的执行顺序。 awk 使用
&& 的短路评估;因此,我们的 x(p) 函数不可能先触发并在评估 $1 == "SCR" 之前销毁 $1。
我们最喜欢的语言 awk 不是线程语言...所以有一点技巧...我们可以修复这个函数,它的实现既高效又“纯粹”...
awk -v p='_RS1c80952b46129fc3bbf7b6d35e52f581d5d96edf' '
function x(v, b, i) {
b=$0
$1=$2=$3=$4=$5=$6=""
i = index($0, v)
$0=b
return i
}
$1 == "SCR" && x(p) {
print $6
}
' inputfile.txt
为什么以上内容很重要?好吧,我们希望我们的函数不改变状态......我们希望我们的函数返回没有副作用......这样我们就可以继续执行而不用担心我们的行缓冲区 - 或其他任何东西 - 已经改变了状态。是的……在最后一个示例中,我们在利用/改变全局状态方面作弊,然后稍后修复它……但最终我们已经修复了它;所以,“没有伤害没有犯规”,嗯?所以......在这个新的实现中,我们实际上可以用 $1 == "SCR" 反转 x(p) 并且没有问题(除了它会更慢)......虽然更复杂的后续程序会受益于使我们的函数“纯” " 因为这种方法更容易思考。