仅连接匹配字符串的行
Concatenate only lines matching strings
我有
文件 1
C2
H1
H2
H3
H4
L1
L10
L2
L3
L4
和文件 2
/C2/C2_CRRA200017850-1a_H3LJWDSXY_L1
/H1/H1_CRRA200017885-1a_H3LJWDSXY_L1
/H1/H1_CRRA200017885-1a_H5MLCDSXY_L1
/H2/H2_CRRA200017886-1a_H3LJWDSXY_L1
/H3/H3_CRRA200017887-1a_H3LJWDSXY_L1
/H4/H4_CRRA200017888-1a_H3LJWDSXY_L1
/L1/L1_CRRA200017897-1a_H3LJWDSXY_L1
/L2/L2_CRRA200017898-1a_H3LJWDSXY_L1
/L3/L3_CRRA200017899-1a_H3LJWDSXY_L1
/L4/L4_CRRA200017900-1a_H3LJWDSXY_L1
/L4/L4_CRRA200017900-1a_H5MLCDSXY_L1
我需要生成一个输出,如果文件 2 中的多行与文件 1 中的字符串匹配,则将它们连接起来,否则打印单行。
/C2/C2_CRRA200017850-1a_H3LJWDSXY_L1
/H1/H1_CRRA200017885-1a_H3LJWDSXY_L1 /H1/H1_CRRA200017885-1a_H5MLCDSXY_L1
/H2/H2_CRRA200017886-1a_H3LJWDSXY_L1
/H3/H3_CRRA200017887-1a_H3LJWDSXY_L1
/H4/H4_CRRA200017888-1a_H3LJWDSXY_L1
/L1/L1_CRRA200017897-1a_H3LJWDSXY_L1
/L2/L2_CRRA200017898-1a_H3LJWDSXY_L1
/L3/L3_CRRA200017899-1a_H3LJWDSXY_L1
/L4/L4_CRRA200017900-1a_H3LJWDSXY_L1 /L4/L4_CRRA200017900-1a_H5MLCDSXY_L1
另一种思路是,如果文件 2 中的行在 // 处具有相同的字符串,则将它们连接起来,否则打印单行。
尝试了几个 grep cmd 但 none 成功了。
我将 GNU AWK
按照以下方式完成此任务,令 file.txt
内容为
/C2/C2_CRRA200017850-1a_H3LJWDSXY_L1
/H1/H1_CRRA200017885-1a_H3LJWDSXY_L1
/H1/H1_CRRA200017885-1a_H5MLCDSXY_L1
/H2/H2_CRRA200017886-1a_H3LJWDSXY_L1
/H3/H3_CRRA200017887-1a_H3LJWDSXY_L1
/H4/H4_CRRA200017888-1a_H3LJWDSXY_L1
/L1/L1_CRRA200017897-1a_H3LJWDSXY_L1
/L2/L2_CRRA200017898-1a_H3LJWDSXY_L1
/L3/L3_CRRA200017899-1a_H3LJWDSXY_L1
/L4/L4_CRRA200017900-1a_H3LJWDSXY_L1
/L4/L4_CRRA200017900-1a_H5MLCDSXY_L1
然后
awk 'BEGIN{FS="/";ORS=""}NR>=2{print (prev!=)?"\n":" "}{print;prev=}' file.txt
产出
/C2/C2_CRRA200017850-1a_H3LJWDSXY_L1
/H1/H1_CRRA200017885-1a_H3LJWDSXY_L1 /H1/H1_CRRA200017885-1a_H5MLCDSXY_L1
/H2/H2_CRRA200017886-1a_H3LJWDSXY_L1
/H3/H3_CRRA200017887-1a_H3LJWDSXY_L1
/H4/H4_CRRA200017888-1a_H3LJWDSXY_L1
/L1/L1_CRRA200017897-1a_H3LJWDSXY_L1
/L2/L2_CRRA200017898-1a_H3LJWDSXY_L1
/L3/L3_CRRA200017899-1a_H3LJWDSXY_L1
/L4/L4_CRRA200017900-1a_H3LJWDSXY_L1 /L4/L4_CRRA200017900-1a_H5MLCDSXY_L1
说明:我将 字段分隔符 (FS
) 设置为 /
,我使用第二列进行比较,因为第一列是空的(有每行中的第一个 /
之前没有任何内容)。我将 输出行分隔符 (ORS
) 设置为空字符串,因为我将自己提供换行符和 spaces。对于每一行,我 print
当前行并将 prev
变量设置为第二列的内容,因此在使用换行符时它确实是 previous 值。对于第二行和后续行(即 number row (NR
) 大于或等于 2),在打印行之前我要么放换行符 \n
if previous value of $2与其他 space
不同,为了做到这一点,我利用 AWK 三元运算,即 condition?
valueiftrue:
valueiffalse。如果您想了解更多有关使用的内置变量的信息,请阅读 8 Powerful Awk Built-in Variables – FS, OFS, RS, ORS, NR, NF, FILENAME, FNR
(在 gawk 4.2.1 中测试)
这可能适合您 (GNU sed):
sed 's#.*#/^\/&\//ba#' file1 |
sed -f - -Ee 'b;:a;N;/^\/([^\/]*)\/.*\n./s/\n/ /;ta;P;D' file2
使用 file1 构建 sed 命令以在 file2 中匹配,如果 file1 中的文字与 file2 中的第一个文字匹配,则跳转到第二次 sed 调用中的某个位置以尝试合并以下行。
sed 的第二次调用使用来自 file1 的输出进行匹配,如果不匹配,则退出。
如果匹配为真,则追加以下行,如果该行也匹配,则删除分隔两行的换行符并重复。
否则,打印模式中两行的第一行space(可能合并的行),删除它并重复。
N.B。如果模式 space 不为空,D
命令会禁止自动读入下一行。
您可能首先将 file1 的所有值存储在一个数组中 ary
。
然后创建一个映射器,其中第一个 //
之间的键存在于 ary 中,并连接由 space.
分隔的行的值
映射器中每个新条目的计数都会增加 1,并在结果数组中打印时使用以保持顺序。
在 END 块中,您可以打印结果数组的值。
awk -v FS="/" '
FNR==NR{
ary[[=10=]];next
}
{
if( in ary){
if(mapper[]) {
mapper[] = mapper[] " " [=10=]
next
}
mapper[] = [=10=];
result[++count] =
next
}
result[++count] = [=10=]
}
END {
for (line = 1; line <= count; line++) {
print result[line] in mapper ? mapper[result[line]] : result[line]
}
}
' file1 file2
示例文件 2
/L1/L1_CRRA200017897-1a_H3LJWDSXY_L1
/C2/C2_CRRA200017850-1a_H3LJWDSXY_L1
/H1/H1_CRRA200017885-1a_H3LJWDSXY_L1
/H1/H1_CRRA200017885-1a_H5MLCDSXY_L1
/H2/H2_CRRA200017886-1a_H3LJWDSXY_L1
/H3/H3_CRRA200017887-1a_H3LJWDSXY_L1
/H4/H4_CRRA200017888-1a_H3LJWDSXY_L1
/L1/L1_CRRA200017897-1a_H3LJWDSXY_L1
/L2/L2_CRRA200017898-1a_H3LJWDSXY_L1
/L3/L3_CRRA200017899-1a_H3LJWDSXY_L1
/L4/L4_CRRA200017900-1a_H3LJWDSXY_L1
/L4/L4_CRRA200017900-1a_H5MLCDSXY_L1
/X9/X9_CRRA200017900-1c_H5MLCDSXY_L1
/X9/X9_CRRA200017900-1c_H5MLCDSXY_L1
/L4/L4_CRRA200017900-1a_H5MLCDSXY_L1
/X8/X8_CRRA200017900-1b_H5MLCDSXY_L1
/X9/X9_CRRA200017900-1c_H5MLCDSXY_L1
输出
/L1/L1_CRRA200017897-1a_H3LJWDSXY_L1 /L1/L1_CRRA200017897-1a_H3LJWDSXY_L1
/C2/C2_CRRA200017850-1a_H3LJWDSXY_L1
/H1/H1_CRRA200017885-1a_H3LJWDSXY_L1 /H1/H1_CRRA200017885-1a_H5MLCDSXY_L1
/H2/H2_CRRA200017886-1a_H3LJWDSXY_L1
/H3/H3_CRRA200017887-1a_H3LJWDSXY_L1
/H4/H4_CRRA200017888-1a_H3LJWDSXY_L1
/L2/L2_CRRA200017898-1a_H3LJWDSXY_L1
/L3/L3_CRRA200017899-1a_H3LJWDSXY_L1
/L4/L4_CRRA200017900-1a_H3LJWDSXY_L1 /L4/L4_CRRA200017900-1a_H5MLCDSXY_L1 /L4/L4_CRRA200017900-1a_H5MLCDSXY_L1
/X9/X9_CRRA200017900-1c_H5MLCDSXY_L1
/X9/X9_CRRA200017900-1c_H5MLCDSXY_L1
/X8/X8_CRRA200017900-1b_H5MLCDSXY_L1
/X9/X9_CRRA200017900-1c_H5MLCDSXY_L1
我有 文件 1
C2
H1
H2
H3
H4
L1
L10
L2
L3
L4
和文件 2
/C2/C2_CRRA200017850-1a_H3LJWDSXY_L1
/H1/H1_CRRA200017885-1a_H3LJWDSXY_L1
/H1/H1_CRRA200017885-1a_H5MLCDSXY_L1
/H2/H2_CRRA200017886-1a_H3LJWDSXY_L1
/H3/H3_CRRA200017887-1a_H3LJWDSXY_L1
/H4/H4_CRRA200017888-1a_H3LJWDSXY_L1
/L1/L1_CRRA200017897-1a_H3LJWDSXY_L1
/L2/L2_CRRA200017898-1a_H3LJWDSXY_L1
/L3/L3_CRRA200017899-1a_H3LJWDSXY_L1
/L4/L4_CRRA200017900-1a_H3LJWDSXY_L1
/L4/L4_CRRA200017900-1a_H5MLCDSXY_L1
我需要生成一个输出,如果文件 2 中的多行与文件 1 中的字符串匹配,则将它们连接起来,否则打印单行。
/C2/C2_CRRA200017850-1a_H3LJWDSXY_L1
/H1/H1_CRRA200017885-1a_H3LJWDSXY_L1 /H1/H1_CRRA200017885-1a_H5MLCDSXY_L1
/H2/H2_CRRA200017886-1a_H3LJWDSXY_L1
/H3/H3_CRRA200017887-1a_H3LJWDSXY_L1
/H4/H4_CRRA200017888-1a_H3LJWDSXY_L1
/L1/L1_CRRA200017897-1a_H3LJWDSXY_L1
/L2/L2_CRRA200017898-1a_H3LJWDSXY_L1
/L3/L3_CRRA200017899-1a_H3LJWDSXY_L1
/L4/L4_CRRA200017900-1a_H3LJWDSXY_L1 /L4/L4_CRRA200017900-1a_H5MLCDSXY_L1
另一种思路是,如果文件 2 中的行在 // 处具有相同的字符串,则将它们连接起来,否则打印单行。
尝试了几个 grep cmd 但 none 成功了。
我将 GNU AWK
按照以下方式完成此任务,令 file.txt
内容为
/C2/C2_CRRA200017850-1a_H3LJWDSXY_L1
/H1/H1_CRRA200017885-1a_H3LJWDSXY_L1
/H1/H1_CRRA200017885-1a_H5MLCDSXY_L1
/H2/H2_CRRA200017886-1a_H3LJWDSXY_L1
/H3/H3_CRRA200017887-1a_H3LJWDSXY_L1
/H4/H4_CRRA200017888-1a_H3LJWDSXY_L1
/L1/L1_CRRA200017897-1a_H3LJWDSXY_L1
/L2/L2_CRRA200017898-1a_H3LJWDSXY_L1
/L3/L3_CRRA200017899-1a_H3LJWDSXY_L1
/L4/L4_CRRA200017900-1a_H3LJWDSXY_L1
/L4/L4_CRRA200017900-1a_H5MLCDSXY_L1
然后
awk 'BEGIN{FS="/";ORS=""}NR>=2{print (prev!=)?"\n":" "}{print;prev=}' file.txt
产出
/C2/C2_CRRA200017850-1a_H3LJWDSXY_L1
/H1/H1_CRRA200017885-1a_H3LJWDSXY_L1 /H1/H1_CRRA200017885-1a_H5MLCDSXY_L1
/H2/H2_CRRA200017886-1a_H3LJWDSXY_L1
/H3/H3_CRRA200017887-1a_H3LJWDSXY_L1
/H4/H4_CRRA200017888-1a_H3LJWDSXY_L1
/L1/L1_CRRA200017897-1a_H3LJWDSXY_L1
/L2/L2_CRRA200017898-1a_H3LJWDSXY_L1
/L3/L3_CRRA200017899-1a_H3LJWDSXY_L1
/L4/L4_CRRA200017900-1a_H3LJWDSXY_L1 /L4/L4_CRRA200017900-1a_H5MLCDSXY_L1
说明:我将 字段分隔符 (FS
) 设置为 /
,我使用第二列进行比较,因为第一列是空的(有每行中的第一个 /
之前没有任何内容)。我将 输出行分隔符 (ORS
) 设置为空字符串,因为我将自己提供换行符和 spaces。对于每一行,我 print
当前行并将 prev
变量设置为第二列的内容,因此在使用换行符时它确实是 previous 值。对于第二行和后续行(即 number row (NR
) 大于或等于 2),在打印行之前我要么放换行符 \n
if previous value of $2与其他 space
不同,为了做到这一点,我利用 AWK 三元运算,即 condition?
valueiftrue:
valueiffalse。如果您想了解更多有关使用的内置变量的信息,请阅读 8 Powerful Awk Built-in Variables – FS, OFS, RS, ORS, NR, NF, FILENAME, FNR
(在 gawk 4.2.1 中测试)
这可能适合您 (GNU sed):
sed 's#.*#/^\/&\//ba#' file1 |
sed -f - -Ee 'b;:a;N;/^\/([^\/]*)\/.*\n./s/\n/ /;ta;P;D' file2
使用 file1 构建 sed 命令以在 file2 中匹配,如果 file1 中的文字与 file2 中的第一个文字匹配,则跳转到第二次 sed 调用中的某个位置以尝试合并以下行。
sed 的第二次调用使用来自 file1 的输出进行匹配,如果不匹配,则退出。
如果匹配为真,则追加以下行,如果该行也匹配,则删除分隔两行的换行符并重复。
否则,打印模式中两行的第一行space(可能合并的行),删除它并重复。
N.B。如果模式 space 不为空,D
命令会禁止自动读入下一行。
您可能首先将 file1 的所有值存储在一个数组中 ary
。
然后创建一个映射器,其中第一个 //
之间的键存在于 ary 中,并连接由 space.
映射器中每个新条目的计数都会增加 1,并在结果数组中打印时使用以保持顺序。
在 END 块中,您可以打印结果数组的值。
awk -v FS="/" '
FNR==NR{
ary[[=10=]];next
}
{
if( in ary){
if(mapper[]) {
mapper[] = mapper[] " " [=10=]
next
}
mapper[] = [=10=];
result[++count] =
next
}
result[++count] = [=10=]
}
END {
for (line = 1; line <= count; line++) {
print result[line] in mapper ? mapper[result[line]] : result[line]
}
}
' file1 file2
示例文件 2
/L1/L1_CRRA200017897-1a_H3LJWDSXY_L1
/C2/C2_CRRA200017850-1a_H3LJWDSXY_L1
/H1/H1_CRRA200017885-1a_H3LJWDSXY_L1
/H1/H1_CRRA200017885-1a_H5MLCDSXY_L1
/H2/H2_CRRA200017886-1a_H3LJWDSXY_L1
/H3/H3_CRRA200017887-1a_H3LJWDSXY_L1
/H4/H4_CRRA200017888-1a_H3LJWDSXY_L1
/L1/L1_CRRA200017897-1a_H3LJWDSXY_L1
/L2/L2_CRRA200017898-1a_H3LJWDSXY_L1
/L3/L3_CRRA200017899-1a_H3LJWDSXY_L1
/L4/L4_CRRA200017900-1a_H3LJWDSXY_L1
/L4/L4_CRRA200017900-1a_H5MLCDSXY_L1
/X9/X9_CRRA200017900-1c_H5MLCDSXY_L1
/X9/X9_CRRA200017900-1c_H5MLCDSXY_L1
/L4/L4_CRRA200017900-1a_H5MLCDSXY_L1
/X8/X8_CRRA200017900-1b_H5MLCDSXY_L1
/X9/X9_CRRA200017900-1c_H5MLCDSXY_L1
输出
/L1/L1_CRRA200017897-1a_H3LJWDSXY_L1 /L1/L1_CRRA200017897-1a_H3LJWDSXY_L1
/C2/C2_CRRA200017850-1a_H3LJWDSXY_L1
/H1/H1_CRRA200017885-1a_H3LJWDSXY_L1 /H1/H1_CRRA200017885-1a_H5MLCDSXY_L1
/H2/H2_CRRA200017886-1a_H3LJWDSXY_L1
/H3/H3_CRRA200017887-1a_H3LJWDSXY_L1
/H4/H4_CRRA200017888-1a_H3LJWDSXY_L1
/L2/L2_CRRA200017898-1a_H3LJWDSXY_L1
/L3/L3_CRRA200017899-1a_H3LJWDSXY_L1
/L4/L4_CRRA200017900-1a_H3LJWDSXY_L1 /L4/L4_CRRA200017900-1a_H5MLCDSXY_L1 /L4/L4_CRRA200017900-1a_H5MLCDSXY_L1
/X9/X9_CRRA200017900-1c_H5MLCDSXY_L1
/X9/X9_CRRA200017900-1c_H5MLCDSXY_L1
/X8/X8_CRRA200017900-1b_H5MLCDSXY_L1
/X9/X9_CRRA200017900-1c_H5MLCDSXY_L1