0
cat << EOF > test.sh

cat $FILEA $FILEB | sort -k1,1 -k2,2n | mergeBed -i - | awk -F\\t '{print $1 "\t" NR "\t\t" $2 "\t" $3 "\t\t.\t\t" NR}' > unionpeaks.gff

EOF

I found $1 $2 $3 can not pass to awk in output file. I got:

cat /file1.narrowPeak /file2.narrowPeak | sort -k1,1 -k2,2n | mergeBed -i - | awk -F\t '{print  "\t" NR "\t\t"  "\t"  "\t\t.\t\t" NR}' > merge.gff
Kusalananda
  • 333,661

2 Answers2

3

The $1, $2 and $3 in the here document are substituted as it catted. At this point the parameters have no meaning, so are replaced by null strings. Consider:

bash-4.4$ cat << EOF > test2.sh
> >$1<>$2<>$3<
> EOF
bash-4.4$ cat test2.sh 
><><><
  • 1
    ... so the solution is to escape the dollar signs or quote the document, whichever is most meaningful to the application. – Kusalananda Mar 13 '22 at 18:05
  • @they, if using cat << 'EOF', the cat $FILEA $FILEB | sort -k1,1 -k2,2n would also have to be changed to cat -- "$FILEA" "$FILEB" | sort -k1,1 -k2,2n or better sort -k1,1 -k2,2n -- "$FILEA" "$FILEB". With cat << EOF, that cat $FILEA $FILEB (where those variables are expanded by the shell that generates the test.sh file) would also be problematic unless those variables are guaranteed not to contain characters special to the shell. – Stéphane Chazelas Mar 13 '22 at 19:39
1

First of all, it's easy to simply point out that the method is a bit redundant. But one thing at a time...

When using cat <<EOF, anything within that can be parsed as an inline command or substitution will be parsed as such. That means that stuff like $1 and $(...) will first be evaluated before the heredoc is created. If you wish to avoid that, the easiest option is to single quote the EOF as such:

cat <<'EOF'
heredoc string stuff in here
EOF

But I'm not sure that is what you want. For whatever you wish to appear in a file, just pipe it there:

cat $FILEA $FILEB | sort -k1,1 -k2,2n | mergeBed -i - | awk -F\\t '{print $1 "\t" NR "\t\t" $2 "\t" $3 "\t\t.\t\t" NR}' > unionpeaks.gff

The heredoc is not necessary. Now, let's look at the cammand per se:

sort -k1,1 -k2,2n -- "$FILEA" "FILEB" | mergeBed -i - | awk -v FS="\t" -v OFS="\t" '{ print $1, NR, "", $2, $3, "", ".", "", NR }' > unionpeaks.gff

cat is simply unnessecary. sort can take file names as input, so no need for an extra call -- I just added a -- to make sure that it doesn't break with files that start with a - (dash). Also, it seems you want tab delimited, so set the OFS (output field separator) to tab. The expected delimiter seems a bit weird as you want double tab for some of them, hence the use of zero-byte strings, i.e. "".

If you simply want that command in a script, then just edit a script file to conatain the script. Combine the EOF learning with the script improvement if the learning about heredocs is the intended purpose. :)