Move line(s) to follow another line in a file

awk, linux

Solution

To answer your last question first, yes, `awk` is the typical Unix tool for this, other candidates are the incredibly powerful `Perl`, `Python`, or .. my favorite .. `Ruby`. One advantage of `awk` is that it's always there; it's part of the base system. Another way to solve this kind of problem is with an editor script that controls `ed(1)` or `ex(1)`.

Ok, new program for the revised question. This program will move the "check" lines either up or down as necessary so that they follow the "files" lines.

BEGIN {
  checkAt = 0
  filesAt = 0
  scanning = 0
}

/check=\(/ {
  checkAt = NR
  scanning = 1
}

/files=\(/ {
  filesAt = NR
  scanning = 1
}

/)$/ {
  if (scanning) {
    if (checkAt > filesAt) {
      checkEnd = NR
    } else {
      filesEnd = NR
    }
    scanning = 0
  }
}

{
  lines[NR] = $0
}

END {
  for (i = 1; i <= NR; ++i) {
    if (checkAt <= i && i <= checkEnd) {
      continue
    }
    print lines[i]
    if (i == filesEnd) {
      for (j = checkAt; j <= checkEnd; ++j) {
        print lines[j]
      }
    }
  }
}

Problem

I got a file that has a line in the file like this: ``` check=('78905905f5a4ed82160c327f3fd34cba') ``` I'd like to be able to move this line to follow a line that looks like this: ``` files=('somefile.txt') ``` The array though at times that can span multiple lines, for example: ``` files=('somefile.txt' 'file2.png' 'another.txt' 'andanother...') text in between check=('78905905f5a4ed82160c327f3fd34cba' '5277a9164001a4276837b59dade26af2' '3f8b60b6fbb993c18442b62ea661aa6b') ``` The array/line always ends in a ) and no text in between will contain a closed parenthesis. I got some advice that awk can do this: ``` awk '/files/{ f=0 print $0 for(i=1;i<=d;i++){ print a[i] } g=0 delete a # remove array after found next } /check/{ f=1; g=1 } f{ a[++d]=$0 } !g' file ``` This will only span one line though. I was told to expand the search: ``` awk '/source/ && /\)$/{ f=0 print $0 for(i=1;i<=d;i++){ print a[i] } g=0 delete a # remove array after found next } /md5sum/ && /\)$/{ f=1; g=1 } f{ a[++d]=$0 } !g' ``` Just learning awk so I'd appreciate help with this. Or if there is another tool that can do this, I'd like to hear about it. Someone told me that 'ed' these types of capabilities.

Original source