repeating the text many times

Viewed 125

I want to repeat the input text 5 times and want to save in another text file.However in every repetition first and last line number only be changed.

My input text is:

READ 1 ALL
DMN 2,3 ^DTND
DEL 2,3
WRITE 1A ALL

OUTPUT:

READ 1 ALL
DMN 2,3 ^DTND
DEL 2,3
WRITE 1A ALL

READ 2 ALL
DMN 2,3 ^DTND
DEL 2,3
WRITE 2A ALL

READ 3 ALL
DMN 2,3 ^DTND
DEL 2,3
WRITE 3A ALL

READ 4 ALL
DMN 2,3 ^DTND
DEL 2,3
WRITE 4A ALL

READ 5 ALL
DMN 2,3 ^DTND
DEL 2,3
WRITE 5A ALL

I tried

#!/bin/sh
for file in `cat input.txt`
do
yes $file
done
6 Answers

You could do this with Perl:

echo 'READ %s ALL
DMN 2,3 ^DTND
DEL 2,3
WRITE %sA ALL' | perl -0777 -nE '
for($x=1; $x<=5; $x++) { say sprintf $_, $x, $x }'

Or in awk:

echo 'READ %s ALL
DMN 2,3 ^DTND
DEL 2,3
WRITE %sA ALL' | awk -v RS= '{for(i=1;i<=5;i++) printf($0 "\n\n",i,i)}'

Same concept in the shell:

s='READ %s ALL
DMN 2,3 ^DTND
DEL 2,3
WRITE %sA ALL'

for i in {1..5}; do
    printf "$s\n\n" "$i" "$i"
done    

If you don't want to create a template for printf to use with %s for your replacements, I would use perl for the more precise regex available:

echo 'READ 1 ALL
DMN 2,3 ^DTND
DEL 2,3
WRITE 1A ALL' | perl -0777 -nE '
for($x=1; $x<=5; $x++) { 
    $s=$_; 
    $s=~s/^(READ |WRITE )(1)(?=\D|$)/$1$x/g; 
    say $s }'

Using GNU awk for gensub():

$ awk -v RS= -v ORS='\n\n' '{for (i=1; i<=5; i++) print gensub(/1/,i,"g")}' file
READ 1 ALL
DMN 2,3 ^DTND
DEL 2,3
WRITE 1A ALL

READ 2 ALL
DMN 2,3 ^DTND
DEL 2,3
WRITE 2A ALL

READ 3 ALL
DMN 2,3 ^DTND
DEL 2,3
WRITE 3A ALL

READ 4 ALL
DMN 2,3 ^DTND
DEL 2,3
WRITE 4A ALL

READ 5 ALL
DMN 2,3 ^DTND
DEL 2,3
WRITE 5A ALL

for file in `cat input.txt` loops over the words in the input file.

yes $file will output the word forever, so your loop will never repeat.

Use a for loop to increment an index from 1 to 5. Then use sed to substitute that into the first and last lines of the file.

for i in {1..5}; do
    sed -e "s/(READ ).*( ALL)/\\1$i\\2/" -e "s/(WRITE ).*(A ALL)/\\1$i\\2/" input.txt
done

Assuming you only want to replace only first and last 1 in string here is a gnu-awk solution:

awk -v RS= '
{
   print
   for (i=2; i<=5; ++i)
      print gensub(/^([^1]*)1(.*)1([^1]*)$/, "\\1" i "\\2" i "\\3", "1")
}' ORS='\n\n' file

READ 1 ALL
DMN 2,3 ^DTND
DEL 2,3
WRITE 1A ALL

READ 2 ALL
DMN 2,3 ^DTND
DEL 2,3
WRITE 2A ALL

READ 3 ALL
DMN 2,3 ^DTND
DEL 2,3
WRITE 3A ALL

READ 4 ALL
DMN 2,3 ^DTND
DEL 2,3
WRITE 4A ALL

READ 5 ALL
DMN 2,3 ^DTND
DEL 2,3
WRITE 5A ALL

Using no programs / processes other than Bash:

repeat_file() {
  local -ir times="${1}"
  local -a lines first_line last_line
  readarray -t lines
  ((${#lines[@]} >= 2)) || return 2
  read -a first_line <<<"${lines[0]}"
  read -a last_line <<<"${lines[-1]}"
  unset 'lines[-1]'
  unset 'lines[0]'
  local -ar lines
  local -i idx
  local line
  for ((idx = 1;;)); do
    echo "${first_line[@]}"
    for line in "${lines[@]}"; do
      echo "${line}"
    done
    echo "${last_line[@]}"
    ((++idx > times)) && break
    ((++first_line[1]))
    last_line[1]="$(("${last_line[1]%A}" + 1))A"
    echo
  done
}

repeat_file 5 < input > output

Another Perl solution:

Updated answer(thanks to dawg)

echo 'READ 1 ALL
DMN 2,3 ^DTND
DEL 2,3
WRITE 1A ALL' | perl -0777 -nE 'while($i++<5) { s/(\d)(?=A? ALL)/$i/g; say }'

Original answer

$ echo 'READ 1 ALL
DMN 2,3 ^DTND
DEL 2,3
WRITE 1A ALL' | perl -0777 -nE ' $_.="\n"; print; 
while($i++<=3) { s/(\d)(?=A? ALL)/$1+1/ge; print } '

Both print:

READ 1 ALL
DMN 2,3 ^DTND
DEL 2,3
WRITE 1A ALL

READ 2 ALL
DMN 2,3 ^DTND
DEL 2,3
WRITE 2A ALL

READ 3 ALL
DMN 2,3 ^DTND
DEL 2,3
WRITE 3A ALL

READ 4 ALL
DMN 2,3 ^DTND
DEL 2,3
WRITE 4A ALL

READ 5 ALL
DMN 2,3 ^DTND
DEL 2,3
WRITE 5A ALL
Related