Home > Software design >  How to increment an integer while passing a multi-line string to a command using "Here tag"
How to increment an integer while passing a multi-line string to a command using "Here tag"

Time:01-14

I have a piece of code that looks similar to this:

index=SOME_INTEGER
SOME_COMMAND <<EOF
subcommand1
${index} subsubcommand1
subcommand2
$((${index} 1)) subsubcommand2
subcommand3
$((${index} 2)) subsubcommand3
subcommand4
$((${index} 3)) subsubcommand4
subcommand5
$((${index} 4)) subsubcommand5
EOF

This method of manually adding one more to ${index} for each new subcommand is quite tedious, and not very practical if i need to rearrange the order/delete lines (the subcommand1 line must precede the subsubcommand1 line and the indexes must be given from lowest to highest), so i was wandering if there was a simple way to increment ${index} between <<EOF and EOF without referencing an exact number, or if there was an alternative way to pass the subcommands to SOME_COMMAND that would allow for this.

I have tried to give various commands like the following but they have not worked:

$((index=$((index 1))))
$((index=index 1))
$((index =1))
$((index  ))

CodePudding user response:

First: If you switch from a postincrement to a preincrement, your original code works. That is:

SOME_COMMAND() { cat; }
 
index=5
 
SOME_COMMAND <<EOF
subcommand1
${index} subsubcommand1
subcommand2
$((  index)) subsubcommand2
subcommand3
$((  index)) subsubcommand3
subcommand4
$((  index)) subsubcommand4
subcommand5
$((  index)) subsubcommand5
EOF

properly emits as output:

subcommand1
5 subsubcommand1
subcommand2
6 subsubcommand2
subcommand3
7 subsubcommand3
subcommand4
8 subsubcommand4
subcommand5
9 subsubcommand5

If that didn't work, though, the easy, surefire thing to do here would be to write a function that generates your desired input. You can then either expand that function into a heredoc or herestring (if SOME_COMMAND needs its input to be seekable), or use it directly as a process substitution (if SOME_COMMAND only needs its input to be streamable).

input_for_SOME_COMMAND() {
  local index mainCommand
  index=$1; shift || return
  for arg; do
    printf '%s\n' "$arg" "$((index  )) sub$arg"
  done
}

SOME_COMMAND <<<"$(input_for_SOME_COMMAND 1 subcommand{1,2,3,4,5})"

See this working in an online sandbox at https://ideone.com/XOUauQ

  • Related