0

I have a text file which contains this:

John
Jack
Jerry

I have another text file:

2017
2015
2018

And I want to make them like this:

John2017
John2015
John2018
Jack2017
Jack2015
Jack2018
Jerry2017
Jerry2015
Jerry2018

How can I do this?

Cfem
  • 1
  • Welcome to Unix & Linux Stack Exchange.  It would appear that you have accidentally created two accounts.  You should use the contact form and select “I need to merge user profiles” to have your accounts merged.  In order to merge them, you will need to provide links to the two accounts.  For your information, these are https://unix.stackexchange.com/users/215567/cfem and https://unix.stackexchange.com/users/215568/cem.  You’ll then be able to [edit], comment on, and accept answers to this question. – G-Man Says 'Reinstate Monica' Feb 12 '17 at 01:36

3 Answers3

3

Assuming that the files are small, it may be viable to read them into arrays (with bash or ksh93):

names=( $( <names.txt ) )
years=( $( <years.txt ) )

You may then construct a double loop that combines each name with each year in turn:

for n in "${names[@]}"; do
  for y in "${years[@]}"; do
    printf '%s%s\n' "$n" "$y"
  done
done

If years.txt is small, but names.txt is large:

years=( $( <years.txt ) )

while read n; do
  for y in "${years[@]}"; do
    printf '%s%s\n' "$n" "$y"
  done
done <names.txt

Result:

John2017
John2015
John2018
Jack2017
Jack2015
Jack2018
Jerry2017
Jerry2015
Jerry2018

Treating the files as single-column, header-less, CSV files:

$ csvsql -H --query "SELECT * FROM names CROSS JOIN years" names.txt years.txt | sed -e '1d' -e 's/,//'

This performs a relational cross join operation on the data in the two tables and then goes on to strip off the first line of the output along with all commas (csvsql creates properly formatted CSV with a header line and comma-separated values).

csvsql is part of csvkit.

Kusalananda
  • 333,661
  • Would be worth noting that in ksh93 / bash, $( <names.txt ) does split+glob (split only in zsh). bash has readarray as a better way to read lines of a file into an array. zsh / fish shells have builtin support to do the cartesian product of 2 arrays ($^a$^b in zsh, $a$b in fish) – Stéphane Chazelas Oct 27 '22 at 19:08
2
$ join -j2 -t : names year | tr -d :
  • join by a non existing field and remove the output field separators.

Field 2 is empty and equal for all the element in names and year so join will concatenate each name with all the years: it is in fact calculating the Cartesian product.

JJoao
  • 12,170
  • 1
  • 23
  • 45
  • 1
    Clever. Though it only seems to work with GNU join. Replacing -j 2 with -1 2 -2 2 would make it standard, but even then I didn't find another implementation beside GNU's where that works. – Stéphane Chazelas Oct 27 '22 at 19:18
  • To tell you the truth I just have access to Linux (GNU everything)... Gnu Join: Once more giving a good semantic to the "corner case" is a blessing to the humanity :-) – JJoao Oct 28 '22 at 21:50
1

The solution that @Kusalananda provided is superior to this one. I provided it without fully thinking through what $(cat ...) does in terms of memory usage. I'll leave it here for reference – it'll work and isn't terrible for if the files are small.

#!/bin/bash

for name in $(cat names); do
    for year in $(cat years); do
        echo "${name}${year}"
    done
done
Andy Dalton
  • 13,993
  • 2
    The reason I didn't go for that solution, and why I mentioned small files, was that the inner file (years) is read once for every line in the first file (names), which may be slow if the files have any kind of non-trivial size. – Kusalananda Feb 11 '17 at 22:46
  • @Kusalananda Good point. The reason that I offered this alternative to your solution was that if the files are large, reading them into memory may not be a good option either. – Andy Dalton Feb 12 '17 at 01:06
  • 1
    And what do you think $(cat names) does? – G-Man Says 'Reinstate Monica' Feb 12 '17 at 01:09
  • @G-Man Doh. You're right, I was thinking about $(cat names) incorrectly. @Kusalananda 's solution is better all around. – Andy Dalton Feb 12 '17 at 01:25