仅连接匹配字符串的行

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