从对中创建对文件

从对中创建对文件

假设我有以下文件:

A 1
B 2
CC 33

我想创建一个包含前一个文件中两个的每个组合的文件,如下所示:

AA 11
AB 12
ACC 133
BA 21
BB 22
BCC 233
CCA 331
CCB 332
CCCC 3333

对于任意文件,可以使用 bash 完成此操作吗?每个条目可以包含除换行符和空格之外的任何字符。某些条目中将包含 UTF-8 字符。

我不在乎顺序。

答案1

您可以完全在 shell 中执行此操作:

while read -r f1 f2
do
    while read -r f3 f4
    do
        printf "%s %s\n" "$f1$f3" "$f2$f4"
    done < your_file
done < your_file

您说,“每个条目可以包含除换行符和空格之外的任何字符。”如果您确实意味着条目可以包含制表符,请说IFS=" " read代替read(两次)。

“细则”:

像这样的命令read f1 f2 会将输入行上的第一个“单词”读入变量f1该行的其余部分进入f2。例如,输入The quick brown fox 将产生f1="The"f2="quick brown fox"。如果您确定您的文件永远不会有三列(或更多)列(即任何行上永远不会有超过两个单词),那么就没有什么可担心的。如果您对不属于第一个单词的所有内容被视为第二个单词的一部分感到满意​​,那么上面的代码应该没问题。 

但是,如果您希望The quick brown fox被视为f1="The"f2="quick",并被brown fox丢弃(忽略),则向每个read命令添加第三个变量。例如,f1 f2会变成f1 f2 x;这将导致f1="The"f2="quick"、 和x="brown fox"。只需不使用$x,我们就丢弃第二个单词之后的输入。第二个read可以类似地更改为read -r f3 f4 x- 因为我们没有使用$x,所以即使我们覆盖它也没关系。如果您愿意使用不同的一次性变量 - 例如… f3 f4 y- 也可以。

默认情况下,该read命令会特殊对待反斜杠 ( \) 字符。基本上,反斜杠后跟任何其他字符合并为第二个字符的特殊版本。因此,\C\C将被读作CC.但更重要的是,反斜杠后跟空格不被视为单词分隔符,反斜杠后跟换行符(即行末尾的反斜杠)不被视为行分隔符/终止符。当我们使用read-r选项调用时,该选项就会停止,反斜杠将成为一个普通字符。以下是一些差异的实际示例:

            不带 -r (默认) __ 带 -r __
_输入_ f1 f2 f1 f2
A\B\\C AB\CA\B\\C
D\EFDEFD\EF    (或 f2="E" 和 x="F")
G\          (这不算一行)        G\
GH GH

所以我在我的第一个答案版本中添加了-r标记。如果您希望能够将其D\ E作为单个单词处理,请不要使用-r

答案2

您可以尝试awk读取文件两次:

awk 'NR == FNR { m[$1] = $2; next; } { for (i in m) { print $1 i, $2 m[i]; } }' file file

答案3

为了保留顺序并避免读取文件两次,我会这样做:

awk '{f1[NR] = $1; f2[NR] = $2}
     END {
       for (i = 1; i <= NR; i++)
        for (j = 1; j <= NR; j++)
          print f1[i]f1[j], f2[i]f2[j]
     }' file

现在,在处理之前将整个文件的内容存储在内存中(就像@taliezin 的方法)。如果您不想这样做,那么您需要读取该文件的次数与文件中的行数一样多@G-Man的方法。但使用awk而不是sh/ bash(这不是为此设计的)会更有效率:

 awk '{f1=$1; f2=$2
       while ((getline < "file") > 0) print f1$1, f2$2
       close("file")}' file

相关内容