我有一个文本文件,其中包含以下内容:
John
Jack
Jerry
我有另一个文本文件:
2017
2015
2018
我想让它们像这样:
John2017
John2015
John2018
Jack2017
Jack2015
Jack2018
Jerry2017
Jerry2015
Jerry2018
我怎样才能做到这一点?
答案1
假设文件很小,将它们读入数组可能是可行的(使用bash
或ksh93
):
names=( $( <names.txt ) )
years=( $( <years.txt ) )
然后,您可以构造一个双循环,依次将每个名称与每年组合起来:
for n in "${names[@]}"; do
for y in "${years[@]}"; do
printf '%s%s\n' "$n" "$y"
done
done
如果years.txt
很小,但names.txt
很大:
years=( $( <years.txt ) )
while read n; do
for y in "${years[@]}"; do
printf '%s%s\n' "$n" "$y"
done
done <names.txt
结果:
John2017
John2015
John2018
Jack2017
Jack2015
Jack2018
Jerry2017
Jerry2015
Jerry2018
将文件视为单列、无标头的 CSV 文件:
$ csvsql -H --query "SELECT * FROM names CROSS JOIN years" names.txt years.txt | sed -e '1d' -e 's/,//'
这执行了一个关系交叉连接对两个表中的数据进行操作,然后继续剥离输出的第一行以及所有逗号(csvsql
创建带有标题行和逗号分隔值的格式正确的 CSV)。
csvsql
是其一部分 csvkit
。
答案2
$ join -j2 -t : names year | tr -d :
- 连接不存在的字段并删除输出字段分隔符。
names
字段 2 为空,并且对于其中的所有元素都相等,year
因此join
会将每个名称与所有年份连接起来:它实际上是在计算笛卡尔积。
答案3
@Kusalananda 提供的解决方案优于此解决方案。我提供它时没有充分考虑$(cat ...)
内存使用方面的影响。我将把它留在这里供参考——它会起作用,而且如果文件很小的话也不会太糟糕。
#!/bin/bash
for name in $(cat names); do
for year in $(cat years); do
echo "${name}${year}"
done
done