Merge 3 files in 1 file in an ordered way

Hi, I have a question that I cannot solve.
if I have a file like this (lets say "x-values.dat"):
x1
x2
x3
another file like this (lets say "y-values.dat"):
y1
y2
y3
y4
and another file like this (lets say "p-values.dat"):
p1
p2
p3
...
p12
How can I get this output?
x1 y1 p1
x1 y2 p2
x1 y3 p3
x1 y4 p4
x2 y1 p5
x2 y2 p6
x2 y3 p7
x2 y4 p8
x3 y1 p9
x3 y2 p10
x3 y3 p11
x3 y4 p12

Any help would be much appreciated

paste -d\  file1 file2 file3

If the all files have the same number of records.

No, the files doesn't have the same number of records (in my example, X has 3 values, Y has 4, and P has 12), and the code you suggested me didn't work, because it merge each line of each file, and that is not what I exactly need.
You can check my first post in order to see the output that I need.

Try this:

awk '{
  while ( (getline y < "y-values.dat") > 0 ) {
    s=$0 FS y
    getline p < "p-values.dat"
    print s FS p
  }
  close("y-values.dat")
}' x-values.dat

The code suggested by Franklin52 worked fine, although it prints 4 lines more. This is the output that I got:
x1 y1 p1
x1 y2 p2
x1 y3 p3
x1 y4 p4
x2 y1 p5
x2 y2 p6
x2 y3 p7
x2 y4 p8
x3 y1 p9
x3 y2 p10
x3 y3 p11
x3 y4 p12
y1 p12
y2 p12
y3 p12
y4 p12

But for the moment it's ok, I can remove these extra lines.
Thank you very much Franklin52!

You have one empty line in the file x-values.dat.

You're right, and now your script is working like a charm :slight_smile:
Tahnk you so much!!

$ for i in x{1..3}; do echo $i; done > x.dat
$ for i in y{1..4}; do echo $i; done > y.dat
$ for i in p{1..12}; do echo $i; done > p.dat

$ perl -nle '
        use integer;

        push @{$h{$ARGV}}, $_;

        END {
                $i=0;
                $fmt = "%10.10s";
                foreach $key ( sort { $#{$h{$a}} <=> $#{$h{$b}} } keys %h) {
                        $c[$i++] = $h{$key};
                }
                
                $j=$#{@c[2]}+1;
                $k=$#{@c[1]}+1;
                $l=$#{@c[0]}+1;
        
                for($i=0, $x=0, $y=0; $i<$j; $i++) {
                        printf $fmt, $c[0][$x+($i*$l/$j)]; 
                        printf $fmt, $c[1][$y++]; 
                        printf "$fmt\n", $c[2][$i];
                        $y=0 if ($y>=$k) ;      
                }
                print "\n";
        }

        ' p.dat y.dat x.dat
        x1        y1        p1
        x1        y2        p2
        x1        y3        p3
        x1        y4        p4
        x2        y1        p5
        x2        y2        p6
        x2        y3        p7
        x2        y4        p8
        x3        y1        p9
        x3        y2       p10
        x3        y3       p11
        x3        y4       p12

Thank you drewk. The code posted by Franklin52 also does the job.

Does that awk script work with different number of lines in the files x y and p?

join -j 2 -o 1.1,2.1 x.dat y.dat |paste -d' ' - p.dat

A bash way

exec 3<p-values.dat
while read X
do    while read Y
    do    read P <&3
        echo "$X $Y $P"
    done < y-values.dat
done < x-values.dat
exec 3>&-

Yes, the script by Franklin works with any number of lines in x (lets say, nx) and y (lets say ny). The number of lines in p (np) has to be np=nx*ny. But this is how I stated the problem..

so it's ok.

Fabulous! It is a very clever awk script btw.

I thought that the length of x, y, and p were arbitrary and that the it was just sorted right to left The perl script I wrote handles any length file x, y, and p and sorts them right to left.

Cheers,

 
xlength=`cat x-values.dat|wc -l`
plength=`cat p-values.dat|wc -l`
ylength=`cat y-values.dat|wc -l`

count=0
if [ $plength != $count ]
 then
  while read -r a
  do
   printf -v line '%*s' "$ylength"
   echo ${line// /$a} | grep -o "$a" >> x-values.datnew
  done < x-values.dat
 let count=$count+1
 else
 break
fi

count=0
while [ $xlength != $count ]
do
 cat y-values.dat>> y-values.datnew
 let count=$count+1
 continue
done

paste -d " " x-values.datnew y-values.datnew p-values.dat > new-values.dat
rm -f x-values.datnew y-values.datnew
cat new-values.dat

# end of script

I'm just a bit curious: I just want to know if my bash solution worked by you. (because it works by me with your sample and is independent of the numbers x and y rows.)

Yes frans, your script worked for me for any number of rows in x-values and y-values (provided np=nx*ny).

Thank you so much!