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


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

2 Answers 2


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<
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.
    – they
    Mar 13 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. Mar 13 at 19:39

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

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. :)

  • 2
    -v FS=OFS="\t" would set FS to the string '"OFS=<tab>" and leave OFS set to a blank.
    – Ed Morton
    Mar 14 at 1:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.