要求:
提取包含 2 个或更多搜索词的文本块,类似于 [ awk ] 中的 [ AND ] 逻辑运算符。
最好在 bash/zsh 函数中作为 awk 运行(但也可以使用独立的 awk 脚本),以正则表达式样式接受输入/参数:
[ A|B|C ] = 返回包含“A”或“B”或“C”的块
[ A&B&C ] = 返回包含所有“A”、“B”和“C”的块
背景: 块之间至少用 5 个新行分隔。
额外: 突出显示搜索匹配项。
给定 [ veganPackage.txt ] 输入文件:
1. Fruits
Apple
Banana
Honey
- tasty combo but too many sugars
- Low prep time
- bad for teeth, cavity warning
2. Drinks
Apple Juice
- served cold and ripe
Add Kiwi
- peel first
Banana Smoothie
- tastes good
- fast power up
3. Veggies
Frillice
Cucumber
Tomato
输入 | 要打印的块 | 给单词上色 |
---|---|---|
苹果|香蕉 | 水果、饮料 | 苹果、香蕉 |
苹果|香蕉|褶边 | 水果、饮料、蔬菜 | 苹果、香蕉、褶边 |
苹果香蕉 | 水果、饮料 | 苹果、香蕉 |
苹果&番茄 | 没什么 | 没什么 |
猕猴桃&香蕉 | 饮料 | 猕猴桃、香蕉(仅限饮料) |
命名为 [ searchBlock ]
searchBlock ()
{
...
awk \
-v RS='\n{4}' \
-v ORS='\n***\n***\n' \
-v color=$colorOut \
-v colorReset=$colorReset \
-v search=$(echo "$searchTerm" | perl -pe 's/(?<!\\)&+/\/&&\//g and s/^/\//g and s/(.)(?=$)/\1\//g') searchTerm \
-v searchAND=$(echo $searchTerm | perl -pe 's/&+/|/g') '$0~search{gsub(searchAND,color"&"colorReset);print}' $file |
vim - -c "/$searchTerm" \
-c ':AnsiEsc' \
-c 'highlight ColorReverse gui=reverse cterm=reverse' \
-c ":match ColorReverse /$searchTerm/"
}
调用示例:
searchBlock -s 'Apple|Banana' veganPackage.txt
'/Apple/&&/Kiwi/{gsub(/(Apple|Kiwi)/,color"&"colorReset);print}' veganPackage.txt
,则按预期输出:\*\*\*
\*\*\*
2. Drinks
Apple Juice
- served cold and ripe
Add Kiwi
- peel first
Banana Smoothie
- tastes good
- fast power
up
\*\*\*
\*\*\*
但是,使用
'$0 ~ search{gsub(searchAND,color"&"colorReset);print}
,[ AND ] 模式#失败(没有打印任何内容)
(不是我过滤/搜索的),但突出显示/着色是正确的)
$0 ~ search
= 对于 awk [ search ] 变量中包含模式的每个块,
{gsub(searchAND,color"&"colorReset);print}
= 打印由 ANSI 转义序列包围的搜索文本的全局替换
看来
$0 ~ /Apple/&&Kiwi/
不与我合作。
输入 | 代码片段 | 结果 | 期待 |
---|---|---|---|
苹果|猕猴桃 |
|
水果、饮料 | 水果、饮料 |
苹果&猕猴桃 |
|
没什么 | 饮料 |
苹果|猕猴桃 |
|
整个文件 | 饮料、水果 |
苹果&猕猴桃 |
|
整个文件 | 饮料 |
苹果&&猕猴桃 |
|
整个文件 | 饮料 |
/苹果/&&/猕猴桃/ |
|
没什么 | 饮料 |
苹果&&猕猴桃 |
|
没什么 | 饮料 |
如何在awk中调试以显示逐行执行中的变量变化+函数返回值?
awk 是否具有与 bash 的 ShellCheck 等效的语法检查器?
是否有比 awk 更直观的文本处理/过滤工具(不是 sed,不是 perl)?
假设:
bash
中)将各种输入解析/重新格式化为awk
一般方法:
gsub/regex
作为 -v variable=value
子句传递awk
脚本为了简化流程,我们将使用以下内容:
$ cat simple.dat
line_1 - Apple
line_2 - Banana
line_3 - Kiwi Cherry Apple
line_4 - Apple Kiwi
line_5 - Kiwi
我们将使用
bash/for
循环来测试一些不同的搜索正则表达式(gsub()
正则表达式对于所有 3 个搜索正则表达式都是相同的):
for search_regex in "/Apple/ && /Kiwi/" "/Apple|Kiwi/" "/Apple/ || /Kiwi/"
do
printf "\n########## search : ${search}\n\n"
awk -v gsub_regex="Apple|Kiwi" '
BEGIN { filler=ignore }
'"${search_regex}"' { gsub(gsub_regex,"__&__") }
1
END { filler=ignore }
' sample.dat
done
注意:这里我假设您可以将各种输入格式解析为两个正则表达式变量的其中一种格式
地点:
awk
脚本的第一部分:
'BEGIN { filler=ignore } '
awk
"${search)regex}"
;必须用双引号括起来awk
' { gsub(gsub_regex,"__&__") } 1; END { filler=ignore }' sample.dat
单引号(第 1/3 部分)和双引号(第 2 部分)之间不能有任何空格
########## search : /Apple/ && /Kiwi/
line_1 - Apple
line_2 - Banana
line_3 - __Kiwi__ Cherry __Apple__
line_4 - __Apple__ __Kiwi__
line_5 - Kiwi
########## search : /Apple|Kiwi/
line_1 - __Apple__
line_2 - Banana
line_3 - __Kiwi__ Cherry __Apple__
line_4 - __Apple__ __Kiwi__
line_5 - __Kiwi__
########## search : /Apple/ || /Kiwi/
line_1 - __Apple__
line_2 - Banana
line_3 - __Kiwi__ Cherry __Apple__
line_4 - __Apple__ __Kiwi__
line_5 - __Kiwi__