我大约有几百个CSV文件。这些CSV文件的定义不同,我不想手动将所有CSV文件合并为一种格式。
我想从文件中获得两个不同的东西-A和B,我可以将它们与正则表达式匹配。我想一次将它们都匹配-因此将只打印同时包含这两种内容的行。我知道该怎么做,而且我已经看到很多SO帖子都回答了如何做。
但是我不知道如何在没有剩余行的情况下仅打印A B
。我不知道这两件事将以什么顺序或以哪几列显示,所以我不知道如何(或什至可以使用)awk。
示例:
(匹配A [0-9],B [0-9])
A0 B0 C0
B1 C1 D1
E2 C2 A2
C3 F3 F3
B4 F4 A4
结果:
A0 B0
A4 B4
答案 0 :(得分:3)
第一个解决方案: :使用match
的{{1}}功能。按照OP显示的示例,它将按字母A到B的顺序输出。
awk
第二个解决方案: 该解决方案将不在乎字母A和B,因此它们以相同的顺序排列。
awk '
match($0,/A[0-9]+/){
val=substr($0,RSTART,RLENGTH)
if(val && match($0,/B[0-9]+/)){
print val,substr($0,RSTART,RLENGTH)
}
}' Input_file
第三个解决方案: :考虑到您需要按输出中从A到B的顺序使用它们,那么以下操作可能会有所帮助。
awk '
{
for(i=1;i<=NF;i++){
if($i ~ /A[0-9]+/ || $i ~ /B[0-9]+/){
val=val?val OFS $i:$i
}
}
if(val ~ /A[0-9]+/ && val ~ /B[0-9]+/){
print val
}
val=""
}
END{
if(val ~ /A[0-9]+/ && val ~ /B[0-9]+/){
print val
}
}' Input_file
注意: :从awk '
{
for(i=1;i<=NF;i++){
line=$i
sub(/[0-9]+/,"",line)
if($i ~ /A[0-9]+/ || $i ~ /B[0-9]+/){
array[tolower(line)]=$i
}
}
if(array["a"] ~ /A[0-9]+/ && array["b"] ~ /B[0-9]+/){
print array["a"],array["b"]
}
delete array
}
END{
if(array["a"] ~ /A[0-9]+/ && array["b"] ~ /B[0-9]+/){
print array["a"],array["b"]
}
}' Input_file
文档中添加有关已使用功能的信息,例如-> man awk
,match
,{{1 }}和tolower
match(s,r [,a])返回s中常规位置 出现表达式r;如果不存在r,则返回0,并设置表达式的值 RSTART 和RLENGTH。请注意,参数顺序与〜运算符的顺序相同:str〜re。如果提供了数组a, 是 清除,然后用匹配对应的s部分填充元素1至n 带括号的 r中的子表达式a的第0个元素包含s中与整个正则表达式r匹配的部分。 子 脚本a [n,“ start”]和a [n,“ length”]分别在字符串和长度中提供 每 匹配的子字符串。
RSTART由match()匹配的第一个字符的索引; 0,如果 没有匹配。 (这意味着字符索引从1开始。)
长度 match();匹配的字符串的长度;如果没有匹配,则为-1。
tolower(str)返回字符串str的副本,其中所有 str中的大写字符转换为它们对应的字符 小写 同行。非字母字符保持不变。
答案 1 :(得分:1)
但是我不知道如何在没有剩余行的情况下仅打印A B。
好吧,您需要从匹配的行中删除除A和B以外的所有内容,并强制awk重新计算字段($1=$1
会这样做)。
awk '/A[0-9]/ && /B[0-9]/ { gsub(/[^AB][0-9]/,""); $1=$1; print }' file