在 CSV 的特定字符串之后打印 3 个连续的列
print 3 consecutive column after specific string from CSV
我需要在特定字符串后打印 2 列(在我的例子中是 64)。同一 CSV 行中可以有多个 64 实例,但是下一个实例不会出现在前一个实例的 3 列内。每个实例的输出应该在下一行并且是唯一的。问题是,特定字符串不会落在所有行的同一列中。所有行都有某种动态数据,CSV 没有 header。比方说,下面是输入文件(它只是一个示例,实际文件有大约 300 列和 500 万个原始文件):
00:TEST,123453103279586,ABC,XYZ,123,456,65,906,06149,NIL TS21,1,64,906,06149,NIL TS22,1,64,916,06149,NIL BS20,1,64,926,06149,NIL BS30,1,64,906,06149,NIL CAML,1,ORIG,0,TERM,1,1,1,6422222222
00:TEST,123458131344169,ABC,XYZ,123,456,OCCF,1,1,1,64,857,19066,NIL TS21,1,64,857,19066,NIL TS22,1,64,857,19066,NIL BS20,1,64,857,19067,NIL BS30,1,64,857,19068,NIL PSS,1,E2 EPSDATA,GRANTED,NONE,1,N,N,256000,5
00:TEST,123458131016844,ABC,XYZ,123,456,HOLD,,1,64,938,36843,NIL TS21,1,64,938,36841,NIL TS22,1,64,938,36823,NIL BS20,1,64,938,36843,NIL BS30,1,64,938,36843,NIL CAML,1,ORIG,0,TERM,00,50000,N,N,N,N
00:TEST,123453102914690,ABC,XYZ,123,456,HOLD,,1,PBS,TS11,64,938,64126,NIL TS21,1,64,938,64126,NIL TS22,1,64,938,64126,NIL BS20,1,64,938,64226,NIL BS30,1,64,938,64326,NIL CAML,1,ORIG,0,TERM,1,1,1,6422222222,2222,R
需要输出(仅唯一条目):
64,906,06149
64,857,19066
64,857,19067
64,857,19068
64,938,36843
64,938,36841
64,938,36823
64,938,36843
64,938,36843
64,938,64326
不存在与性能相关的问题。我试图搜索许多线程,但找不到任何相关的东西。请帮忙
我们可以使用两个命令的管道...第一个是将 64 的前导放在一行上,第二个是打印前三列(如果我们看到前导 64)。
sed 's/,64[,\n]/\n64,/g' | awk -F, '/^64/ { print FS FS }'
有多种方法可以使用单个 awk 命令来完成此操作,但这对我来说感觉又快又简单。
尽管问题中的示例数据包含冗余行,但 karakfa(见下文)提醒我该问题涉及 "unique data" 要求。此版本使用关联数组的键来跟踪重复记录。
sed 's/,64[,\n]/\n64,/g' | awk -F, 'BEGIN { split("",a) } /^64/ && !((x= FS FS ) in a) { a[x]=1; print x }'
傻眼:
awk -F, '{for(i=0;++i<=NF;){if($i=="64")a=4;if(--a>0)s=s?s","$i:$i;if(a==1){print s;s=""}}}' file
Sed 的乐趣
sed -n -e 's/$/,n,n,n/' -e ':a' -e 'G;s/[[:blank:],]\(64,.*\)\(\n\)$//;s/.*\(\n\)\(64\([[:blank:],][^[:blank:],]\{1,\}\)\{2\}\)\([[:blank:],][^[:blank:],]\{1,\}\)\{3\}\([[:blank:],].*\)\{0,1\}$//;s/^.*\n\(.*\n\)//;/^64.*\n/P;s///;ta' YourFile | sort -u
假设列由空格 space 或逗号分隔
需要一个 sort -u 用于 uniq(可能在 sed 中,但在这种情况下要添加一个新的 "simple" 同类动作)
awk
救援!
$ awk -F, '{for(i=1;i<=NF;i++)
if($i==64)
{k=$i FS $(++i) FS $(++i);
if (!a[k]++)
print k
}
}' file
64,906,06149
64,916,06149
64,926,06149
64,857,19066
64,857,19067
64,857,19068
64,938,36843
64,938,36841
64,938,36823
64,938,64126
64,938,64226
64,938,64326
ps。您的示例输出与给定的输入不匹配。
我需要在特定字符串后打印 2 列(在我的例子中是 64)。同一 CSV 行中可以有多个 64 实例,但是下一个实例不会出现在前一个实例的 3 列内。每个实例的输出应该在下一行并且是唯一的。问题是,特定字符串不会落在所有行的同一列中。所有行都有某种动态数据,CSV 没有 header。比方说,下面是输入文件(它只是一个示例,实际文件有大约 300 列和 500 万个原始文件):
00:TEST,123453103279586,ABC,XYZ,123,456,65,906,06149,NIL TS21,1,64,906,06149,NIL TS22,1,64,916,06149,NIL BS20,1,64,926,06149,NIL BS30,1,64,906,06149,NIL CAML,1,ORIG,0,TERM,1,1,1,6422222222
00:TEST,123458131344169,ABC,XYZ,123,456,OCCF,1,1,1,64,857,19066,NIL TS21,1,64,857,19066,NIL TS22,1,64,857,19066,NIL BS20,1,64,857,19067,NIL BS30,1,64,857,19068,NIL PSS,1,E2 EPSDATA,GRANTED,NONE,1,N,N,256000,5
00:TEST,123458131016844,ABC,XYZ,123,456,HOLD,,1,64,938,36843,NIL TS21,1,64,938,36841,NIL TS22,1,64,938,36823,NIL BS20,1,64,938,36843,NIL BS30,1,64,938,36843,NIL CAML,1,ORIG,0,TERM,00,50000,N,N,N,N
00:TEST,123453102914690,ABC,XYZ,123,456,HOLD,,1,PBS,TS11,64,938,64126,NIL TS21,1,64,938,64126,NIL TS22,1,64,938,64126,NIL BS20,1,64,938,64226,NIL BS30,1,64,938,64326,NIL CAML,1,ORIG,0,TERM,1,1,1,6422222222,2222,R
需要输出(仅唯一条目):
64,906,06149
64,857,19066
64,857,19067
64,857,19068
64,938,36843
64,938,36841
64,938,36823
64,938,36843
64,938,36843
64,938,64326
不存在与性能相关的问题。我试图搜索许多线程,但找不到任何相关的东西。请帮忙
我们可以使用两个命令的管道...第一个是将 64 的前导放在一行上,第二个是打印前三列(如果我们看到前导 64)。
sed 's/,64[,\n]/\n64,/g' | awk -F, '/^64/ { print FS FS }'
有多种方法可以使用单个 awk 命令来完成此操作,但这对我来说感觉又快又简单。
尽管问题中的示例数据包含冗余行,但 karakfa(见下文)提醒我该问题涉及 "unique data" 要求。此版本使用关联数组的键来跟踪重复记录。
sed 's/,64[,\n]/\n64,/g' | awk -F, 'BEGIN { split("",a) } /^64/ && !((x= FS FS ) in a) { a[x]=1; print x }'
傻眼:
awk -F, '{for(i=0;++i<=NF;){if($i=="64")a=4;if(--a>0)s=s?s","$i:$i;if(a==1){print s;s=""}}}' file
Sed 的乐趣
sed -n -e 's/$/,n,n,n/' -e ':a' -e 'G;s/[[:blank:],]\(64,.*\)\(\n\)$//;s/.*\(\n\)\(64\([[:blank:],][^[:blank:],]\{1,\}\)\{2\}\)\([[:blank:],][^[:blank:],]\{1,\}\)\{3\}\([[:blank:],].*\)\{0,1\}$//;s/^.*\n\(.*\n\)//;/^64.*\n/P;s///;ta' YourFile | sort -u
假设列由空格 space 或逗号分隔 需要一个 sort -u 用于 uniq(可能在 sed 中,但在这种情况下要添加一个新的 "simple" 同类动作)
awk
救援!
$ awk -F, '{for(i=1;i<=NF;i++)
if($i==64)
{k=$i FS $(++i) FS $(++i);
if (!a[k]++)
print k
}
}' file
64,906,06149
64,916,06149
64,926,06149
64,857,19066
64,857,19067
64,857,19068
64,938,36843
64,938,36841
64,938,36823
64,938,64126
64,938,64226
64,938,64326
ps。您的示例输出与给定的输入不匹配。