0

I have a main file which has ONLY one matched string and I would like to change the values of one of the columns in the 2nd line after that matched phrase and output to a separate file. I have another reference file which has the output filenames (1st column) and the replacement values (2nd column). Below is the sample and my attempted code with error and without any output. I appreciate your support.

(main_file)

some words here
This is the 'MATCH LINE'
# this is just a comment
This NUMBER to be updated
and other words here

(ref_file)

Out1 ONE
Out2 TWO
Out3 THREE

(expected output file: Out1)

some words here
This is the 'MATCH LINE'
# this is just a comment
This ONE to be updated
and other words here

(expected output file: Out2)

some words here
This is the 'MATCH LINE'
# this is just a comment
This TWO to be updated
and other words here

(expected output file: Out3)

some words here
This is the 'MATCH LINE'
# this is just a comment
This THREE to be updated
and other words here

My attempted script:

awk 'FNR==NR {fn[$2]=$1; vals[$2]=$2; next}
   {for (f in fn) {$0~/This is the '\''MATCH LINE'\''/{getline;getline;$2=vals[f]}}; print $0 > fn[f]}' ref_file  main_file

Error maessage:

awk: file "[command line]": line 1: Syntax error  Context is:
>>>
>>>        {for (f in fn) {$0~/This is the 'MATCH LINE'/{       <<<
Ed Morton
  • 188,023
  • 17
  • 78
  • 185
  • 2
    please update the question to show the complete error/output generated by your `awk` script – markp-fuso Jun 13 '23 at 12:16
  • In your real data can whatever string is represented by `'MATH_LINE'` or `NUMBER` in your example ever contain regexp metachars or spaces or be present as a substring of some other string that you do not want to match? Can whatever string is represented by `ONE`, etc. in your example ever contain backreference metachars such as `&` or spaces or be present in a substring you do not want to match? Can the file names `Out1`, etc. ever contain space chars? If the answer to any of those questions is "yes" then please [edit] your example to include the more truly representative rainy day case(s). – Ed Morton Jun 15 '23 at 13:25

4 Answers4

5

I've seen a couple of your questions and you seem a bit confused on how to process multiple files. While you can use getline() to read information that is outside the records of the current file, when processing 2 files for coordinating information, it is rarely needed.

Instead you will order the processing of the files so you capture what you need from the first file, either in an array (normally) or by concatenating information in a string (provides benefit in some cases), and then reading records from the second file and applying whatever changes are needed. You correctly use FNR==NR to check the current file record number is equal the total number of records to identify when reading from the first file provided. But then your script kind of meanders away from what you want.

In your ref file, all you really care about is the second field. Just read that into an array skipping the remainder of the rules, e.g.

awk 'FNR==NR {a[++n]=$2; next} ... '

(note: by using pre-increment for the array index (++n), you keep the index consistent with the 1-based processing of the record number, etc...)

Now all you need is one more rule (actually two -- considering the use of the default print rule), e.g.

' ... $1 && ++line==3 && i<=n {sub(/NUMBER/,a[++i]); line=0}1'

Now let's go through the logic processing the main file. The first thing you need is a simple variable line to track 1, 2, 3 (replace), reset to 0. So if you look at the conditional $1 && ++line==3 && i<=n it says:

  • if there is a first field (e.g. not just an empty line); then
  • pre-increment line and compare it to 3; and finally
  • make sure you haven't run out of saved replacement numbers.

(note: since it is an AND comparison, on the first false criteria, the remainder are never checked preventing ++line from executing on blank lines)

If all three conditions are met, then you just substitute the number saved as a[++i] for /NUMBER/ using sub(). The 1 at the end of the rule is just shorthand for the default rule print.

Example Use/Output

With your ref file in dat/ref (does not contain [ref] which I take as your way of giving a filename) and longer main in dat/main, e.g.

$ cat dat/main
This is the 'MATCH LINE'
# this is just a comment
This NUMBER to be updated

This is the 'MATCH LINE'
# this is just a comment
This NUMBER to be updated

Then you would use the full awk expression as:

$ awk 'FNR==NR {a[++n]=$2; next} $1 && ++line==3 && i<=n {sub(/NUMBER/,a[++i]); line=0}1' dat/ref dat/main
This is the 'MATCH LINE'
# this is just a comment
This ONE to be updated

This is the 'MATCH LINE'
# this is just a comment
This TWO to be updated

Which is the output you specify -- but I suspect you actually need a bit more to handle other lines that may be in your file....

If You Have Additional Lines In The [main] File

If your [main] file can have all kinds of other lines in it, then you need to track whether you have found a matched line and are in your 1, 2, 3 count. You can do that with small changes using the line variable as a flag and counter like:

awk 'FNR==NR {a[++n]=$2; next} line && ++line==3 && i<=n {sub(/NUMBER/,a[++i]); line=0} /MATCH LINE/ {line = 1}1' dat/ref dat/main

Here we are using line as a flag and a counter that is set to 1 (true) if you find a line with "MATCH LINE" in it. You toggle the line flag off when you make your replacement. That way any other lines that may come along are simply printed unchanged. For example lets say your [main] file now contains:

$ cat dat/main
@#$#% stuff
more stuff

###whatever
This is the 'MATCH LINE'
# this is just a comment
This NUMBER to be updated

@#$$%

This is the 'MATCH LINE'
# this is just a comment
This NUMBER to be updated

Now you simply make the replacements on the 2nd line after the "MATCH LINE", e.g.

$ awk 'FNR==NR {a[++n]=$2; next} line && ++line==3 && i<=n {sub(/NUMBER/,a[++i]); line=0} /MATCH LINE/ {line = 1}1' dat/ref dat/main
@#$#% stuff
more stuff

###whatever
This is the 'MATCH LINE'
# this is just a comment
This ONE to be updated

@#$$%

This is the 'MATCH LINE'
# this is just a comment
This TWO to be updated

Which again is what you specify as wanting for output shown with two replacements, but done in a file that can have all kinds of other lines (like normal files do).

Let me know if you have questions, or if you actually have the lines [ref] and [main] in your input files.


Update For Your Edit To Redirect Single Replacement Line to Filename $1 in [ref]

Okay, per your comment:

@DavidC.Rankin: I understood your thought. You assumed I have several 'MATCH LINE' in dat/main file. I should emphasize that dat/main file has ONLY one 'MATCH LINE' that we use an anchor to modify the following second line and replace the NUMBER with One/Two and Three and output each file to separate files, named per the first column of dat/ref (i.e. Out1, Out2 & Out3).

To redirect to a file named by the 1st field in [ref] (my dat/ref) all you need to do is save the first field in a separate array (or you can just save the complete line and split it later). Let's use a filename array using the same n as the index, e.g. fn[++n] (we increment with fn[] now since we place it first -- you can order it however you like). The only change needed to save the first field in dat/ref in the filename array is:

... 'FNR==NR {fn[++n]=$1; a[n]=$2; next} ...

With the first file saved, we no longer want to use the default print command to output each records in the 1, 2, 3 count, we only want to output the substituted line to the new file. So remove the 1 from the end and now just redirect after setting line=0;, e.g.

... line && ++line==3 && i<=n {sub(/NUMBER/,a[++i]); line=0; print > fn[i]} ...

(for me I like to create output files in the dat/ directory, so you can simply let awk concatenate the directory for you, e.g.

... print > ("dat/" fn[i]) ...

(Thank you Ed for pointing the precedence issue out to make it work with all awks)

Putting it altogether and outputting the new files to the dat/ directory, you would have:

awk 'FNR==NR {fn[++n]=$1; a[n]=$2; next} line && ++line==3 && i<=n {sub(/NUMBER/,a[++i]); line=0; print > ("dat/" fn[i])} /MATCH LINE/ {line = 1}' dat/ref dat/main

New Files Created

Since I only have 2 sets of statements in dat/main, I get just two new files, e.g.

$ ls -al dat/out*
-rw-r--r-- 1 david david 23 Jun 12 23:20 dat/out1
-rw-r--r-- 1 david david 23 Jun 12 23:20 dat/out2

And the content is as you specify, a single line containing the substitution, e.g.

$ cat dat/out1
This ONE to be updated

and

$ cat dat/out2
This TWO to be updated

Let me know if we have finally has a "meeting-of-the-minds" and communicated and understood what you are wanting to accomplish.

(note: as Ed mentions, if there is nothing special about the spacing in the output, e.g. no special number of whitespace you are needing to preserve, and if NUMBER is always the 2nd field, you can simply set $2 = a[++i] instead of using sub(/NUMBER/,a[++i]).)


Additional Edit to Now Write All Lines To Output file (MATCH through substition)

If you now want to write the MATCH line, the next line and the changed line to the file specified by the 1st field in ref, you can add a variable (say content) to accumulate each of the lines and then print redirecting them to the file, e.g.

awk 'FNR==NR {fn[++n]=$1; a[n]=$2; next} line && ++line==3 && i<=n {sub(/NUMBER/,a[++i]); line=0; content = content $0; print content > ("dat/" fn[i]); content = ""} /MATCH LINE/ {line = 1} line > 0 {content = content $0 "\n"}' dat/ref dat/main

Files Created

Same dat/out1 and dat/out2, but now with the content:

$ cat dat/out1
This is the 'MATCH LINE'
# this is just a comment
This ONE to be updated

and

$ cat dat/out2
This is the 'MATCH LINE'
# this is just a comment
This TWO to be updated

When the command line gets this long, it's easier just to create an awk script, say matchline.awk and make it executable with chmod +x matchline.awk. Now you can read the script a lot easier and all you need to do to run it is, e.g. with my dat/ref and dat/main is:

$ ./matchline.awk dat/ref dat/main

The full awk script would be:

#!/bin/awk -f

FNR == NR {         ## process ref file
  fn[++n] = $1      ## saving 1st field to array fn[]
  a[n] = $2         ## savind 2nd filed to array a[]
  next              ## skip to next record
}

line && ++line == 3 && i <= n {   ## if line set and 3 and array element reamin
  sub(/NUMBER/,a[++i])            ## substitute 2nd field for NUMBER
  content = content $0            ## append
  print content > ("dat/" fn[i])  ## output saved content to 1st field name
  line = 0                        ## reset line 0
  content = ""                    ## reset content empty
}

/MATCH LINE/ {      ## if line has 'MATCH LINE'
  line = 1          ## set line to 1
}

line > 0 {                        ## if line set
  content = content $0 "\n"       ## append to contents with newline
}

(same files created)


Per your last comment:

@DavidC.Rankin: I tried last edit (the long awk script) with only change of removing "dat/" from the print print content > (fn[i]) , but it only generated the first output (Out1)

If not using a separate directory for the input/output files (e.g. "dat/"), then there is no need to enclose the filename concatenation in ( ... ). All you need is print content > fn[i]. The whole script with "dat/" removed would be:

#!/bin/awk -f

FNR == NR {         ## process ref file
  fn[++n] = $1      ## saving 1st field to array fn[]
  a[n] = $2         ## savind 2nd filed to array a[]
  next              ## skip to next record
}

line && ++line == 3 && i <= n {   ## if line set and 3 and array element reamin
  sub (/NUMBER/, a[++i])          ## substitute 2nd filed for NUMBER
  content = content $0            ## append
  print content > fn[i]           ## output saved content
  line = 0                        ## reset line 0
  content = ""                    ## reset content empty
}

/MATCH LINE/ {      ## if line has 'MATCH LINE'
  line = 1          ## set line to 1
}

line > 0 {                        ## if line set
  content = content $0 "\n"       ## append to contents with newline
}

Files Created in Present Directory

Now with the two sets of input in main shown above and your ref, you run in the same way:

$ ./matchline.awk ref main

Before running the script, the only files present in the directory were:

$ ls -al
total 20
drwxr-xr-x  2 david david 4096 Jun 15 16:51 .
drwxr-xr-x 10 david david 4096 Jun 15 16:50 ..
-rw-r--r--  1 david david  153 Jun 15 16:50 main
-rwxr-xr-x  1 david david 1009 Jun 15 16:51 matchline.awk
-rw-r--r--  1 david david   29 Jun 15 16:50 ref

After (with contents shown), you have

$ 16:51 wizard:~/tmp/awk/tst> ./matchline.awk ref main
16:51 wizard:~/tmp/awk/tst> l
total 28
drwxr-xr-x  2 david david 4096 Jun 15 16:51 .
drwxr-xr-x 10 david david 4096 Jun 15 16:50 ..
-rw-r--r--  1 david david  153 Jun 15 16:50 main
-rwxr-xr-x  1 david david 1009 Jun 15 16:51 matchline.awk
-rw-r--r--  1 david david   73 Jun 15 16:51 out1
-rw-r--r--  1 david david   73 Jun 15 16:51 out2
-rw-r--r--  1 david david   29 Jun 15 16:50 ref
16:51 wizard:~/tmp/awk/tst> cat out1
This is the 'MATCH LINE'
# this is just a comment
This ONE to be updated
16:51 wizard:~/tmp/awk/tst> cat out2
This is the 'MATCH LINE'
# this is just a comment
This TWO to be updated

Which is exactly what you have described as wanting. Remove the (...) in the redirection statement and give it another go. Also show me the exact output of awk --version on your system if you are still having issues. I've run into some strange awk issues where the OP was using a 20 year old awk on a Sun Sparkstation --so we need to eliminate that issue if you still have problems.


Changes to Generalize 2nd Field Replacement in main

To generalize the replacement of the 2nd field in main instead of replacing NUMBER, you can simply change the sub() command to an assignment to the 2nd field. The rule with the changes is shown below, the rest of the script is unchanged. You are just replacing the sub() line with an assignment to $2 as Ed mentioned in a comment earlier, e.g.

line && ++line == 3 && i <= n {   ## if line set and 3 and array element reamin
  # sub (/NUMBER/, a[++i])          ## substitute 2nd field for NUMBER
  $2 = a[++i];                    ## assign save 2nd field to replace 2nd field
  content = content $0            ## append
  print content > fn[i]           ## output saved content
  line = 0                        ## reset line 0
  content = ""                    ## reset content empty
}

(original sub() command commented and new assignment below it)

Results are the same as the last example above.

Let me know if you have questions.

David C. Rankin
  • 81,885
  • 6
  • 58
  • 85
  • Thanks Ed, yes that is likely the case. It was a bit confusing to get from the description. The use of `sub()` was to prevent recalculation of the the fields in case spacing was to be preserved (to the extent possible). But if that is just a sentence, then it wouldn't really matter. (though I suspect the actual data is a bit different from the example). Maybe not... – David C. Rankin Jun 10 '23 at 15:33
  • @DavidC.Rankin: Thanks so much for your thorough useful response. Actually, my main file contains ONLY one MATCH LINE and the second line below that will be processed. However, when I run the latest script, it only process the first line of ref (Out1/ One) and prints the result (instead of print to the Out1 file). I wonder how it can be modified? – EverLearner Jun 12 '23 at 12:49
  • There must be some other difference, I just copy/pasted from my 2nd command line using your original `main` file and get `"This ONE to be updated"` -- is that not what you get? (what is the file encoding on your file? Was it created on Windows?) Run `file main` and make sure the output is `main: ASCII text` If you see anything like utf-16 encoding -- then awk will not know how to handle that file. (windows notepad writes utf-16 files by default...) – David C. Rankin Jun 12 '23 at 13:16
  • Note: the difference in line-endings between Linux and DOS (`'\n'` verses `'\r\n'`) makes no difference here. – David C. Rankin Jun 12 '23 at 13:18
  • @DavidC.Rankin: I understood your thought. You assumed I have several 'MATCH LINE' in dat/main file. I should emphasize that dat/main file has ONLY one 'MATCH LINE' that we use an anchor to modify the following second line and replace the NUMBER with One/Two and Three and output each file to separate files, named per the first column of dat/ref (i.e. Out1, Out2 & Out3). Could you please advise? – EverLearner Jun 12 '23 at 18:50
  • Okay, now we are communicating. I'll do another command line for you. – David C. Rankin Jun 13 '23 at 04:15
  • @DavidC.Rankin: Thanks, that would be a great help David. – EverLearner Jun 13 '23 at 21:25
  • @EverLearner - you now want all lines (including the substituted line) written to the output file specified by the 1st field in `ref`? (also -- if `main` has more lines in it than just the `MATCH` line and the 2 lines that follow (blank lines, stray text) where must the extra text go? – David C. Rankin Jun 15 '23 at 03:43
  • @DavidC.Rankin: Thanks for the follow up. 1st question: Yes | 2nd question: main file could have many lines, all its lines will be mirrored to each output file and ONLY one field in that specific line (2nd after the MATCH line) will be substituted. – EverLearner Jun 15 '23 at 04:14
  • "all its lines" or just `MATCH` line, next line and 2nd line with change? My understanding is you want `MATCH` line, next line and 2nd line with change... Let me know. – David C. Rankin Jun 15 '23 at 04:34
  • Apology for the miscommunication. I want ALL its lines to be copied to the output. I just edited the question. – EverLearner Jun 15 '23 at 05:12
  • @EverLearner - great - that's what my last edit to the answer does. – David C. Rankin Jun 15 '23 at 05:21
  • @DavidC.Rankin: I tried last edit (the long awk script) with only change of removing "dat/" from the print ```print content > (fn[i])``` , but it only generated the first output (Out1) – EverLearner Jun 15 '23 at 13:27
  • @EverLearner - see last edit. – David C. Rankin Jun 15 '23 at 21:59
  • 1
    Also, never DELETE information from your question. When you make changes, simply ADD new information below your original question. That way all comments and answers still make sense. – David C. Rankin Jun 15 '23 at 23:15
  • Dave and Ed: thank you so much for your dedication and help. A quick follow-up question: is it possible to use the 2nd field instead of the word "NUMBER"? just want to generalize the script – EverLearner Jun 19 '23 at 20:49
  • Yes. Instead of using `sub()` with `/NUMBER/`, just set `$2 = a[++i]` in the script as Ed suggested above. As long as you do not have to preserve any odd spacings between fields in `main`, then that will work fine. Then you are just swapping whatever the 2nd field is with the value saved from `ref`. – David C. Rankin Jun 20 '23 at 09:48
  • Dave: How can I generalize the 2nd field of ```ref``` using your script? – EverLearner Jun 20 '23 at 10:57
  • 1
    See new edit -- it is just as I described in my comment. You are just using `$2 = a[++i]` instead of `sub (/NUMBER/, a[++i])`. Let me know if you still have issues. Remember if you have multiple spaces as separators, they will be collapsed into a single separator when awk recalculates the fields after assignment (the reason I used `sub()` to avoid to begin with) You could use `sub ($2, a[++i])` (or create a dynamic REGEX) if spacing becomes an issue. – David C. Rankin Jun 21 '23 at 03:45
  • Dave, does your latest script accept ``main``` files with several lines (e.g. the one shown in current edited question)? I suspected you wrote the script based on the initial statement with ```main``` having 3 lines as your examples show. – EverLearner Jun 21 '23 at 19:47
  • No, sorry, my `main` has 2 sets on groupings. See the output after the very first `cat dat/main` above -- all `main` used whether in the `dat/` directory or not has both groups in it. (the `main` with all the extraneous lines -- in addition to -- the two groupings was used for the examples where shown above) – David C. Rankin Jun 22 '23 at 05:06
1

Solution in TXR Lisp.

Here we assume that the main_file can contain material before the MATCH LINE as well as arbitrary trailing material.

This is in a file called gen.tl:

(match `@prolog\n                   \
        This is the 'MATCH LINE'\n  \
        @skipline\n                 \
        @{before}NUMBER@{after}\n   \
        @epilog`
        (file-get-string "main_file")
  (each-match (`@outfile @string` (file-get-lines "ref_file"))
    (file-put-string outfile
                     `@prolog\n                   \
                      This is the 'MATCH LINE'\n  \
                      @skipline\n                 \
                      @before@string@after\n      \
                      @epilog`)))

Test:

$ cat main_file
# stuff before
This is the 'MATCH LINE'
# this is just a comment
This NUMBER to be updated
# stuff after
$ rm Out*
$ txr gen.tl
$ cat Out1
# stuff before
This is the 'MATCH LINE'
# this is just a comment
This ONE to be updated
# stuff after
$ cat Out2
# stuff before
This is the 'MATCH LINE'
# this is just a comment
This TWO to be updated
# stuff after
$ cat Out3
# stuff before
This is the 'MATCH LINE'
# this is just a comment
This THREE to be updated
# stuff after
Kaz
  • 55,781
  • 9
  • 100
  • 149
1

Making several assumptions about what your real data values might be (e.g. that the key strings don't contain unstated white space, regexp metachars, and backreference metachars and can't appear undesirably as substrings), this might do what you want, using any awk:

$ cat tst.awk
NR == FNR {
    lines[++numLines] = $0
    if ( /\047MATCH LINE\047/ ) {
        tgt = NR + 2
    }
    next
}
{
    for ( lineNr=1; lineNr<=numLines; lineNr++ ) {
        line = lines[lineNr]
        if ( lineNr == tgt ) {
            sub(/NUMBER/,$2,line)
        }
        print line > $1
    }
    close($1)
}

$ awk -f tst.awk main_file ref_file

$ head Out*
==> Out1 <==
some words here
This is the 'MATCH LINE'
# this is just a comment
This ONE to be updated
and other words here

==> Out2 <==
some words here
This is the 'MATCH LINE'
# this is just a comment
This TWO to be updated
and other words here

==> Out3 <==
some words here
This is the 'MATCH LINE'
# this is just a comment
This THREE to be updated
and other words here

By the way, Your syntax error is because you forgot the if. You wrote:

$0~/This is the '\''MATCH LINE'\''/

instead of:

if ( $0~/This is the '\''MATCH LINE'\''/ )

If you had written your original script formatted legibly with indenting and line breaks:

awk '
    FNR == NR {
            fn[$2] = $1
            vals[$2] = $2
            next
    }

    {
            for (f in fn) {
                    $0 ~ /This is the '\''MATCH LINE'\''/ {
                            getline
                            getline
                            $2 = vals[f]
                    }
            }
            print($0) > fn[f]
    }
' ref_file main_file

instead of cramming it all into 1 line then when awk told you you had a syntax error:

awk: cmd. line:10:                     $0 ~ /This is the 'MATCH LINE'/ {
awk: cmd. line:10:                                                     ^ syntax error

it'd have been MUCH easier for you to identify where the error is (note the now-relevant line number in the error message) and debug it (note how obvious the missing if is).

A couple of other things -

  1. Don't be so quick to use getline as it's rarely the best solution and is easy to get wrong, see http://awk.freeshell.org/AllAboutGetline.
  2. If you use \047 instead of '\'' to represent 's then your script will work in a file (awk -f scriptfile input) or on the command line (awk 'script' input) rather than just the latter.
Ed Morton
  • 188,023
  • 17
  • 78
  • 185
  • Ed: I run your latest script with the same syntax in Korn Shell, but I still get only 1 output (Out1) file ! – EverLearner Jun 20 '23 at 10:58
  • As you can see in my answer, given the sample input you provided my script does produce the output you provided so if that's not what you're seeing then either you did something wrong when copy/pasting the script or your input doesn't actually look like the input you showed us. – Ed Morton Jun 20 '23 at 11:26
  • My mistake, I had swapped the order of the input files. It works now. As for generalization of the 2nd field of ```ref``` to accept any word, I used ```$2 = a[++i]``` instead of ```sub(/NUMBER/,a[++i])``` but it does not generate any output. Can you advise? – EverLearner Jun 20 '23 at 14:58
  • Using `$2 = a[++i]` instead of `sub(/NUMBER/,a[++i])` doesn't make sense as I have neither an array named `a[]` nor a variable named `i` in my script but it will not cause the script to not produce any output. Anyway, [Chameleon Questions](https://meta.stackexchange.com/questions/43478/exit-strategies-for-chameleon-questions) are strongly discouraged on this forum, just ask a new question. – Ed Morton Jun 20 '23 at 15:17
  • 1
    Ed, thanks for reminding me the forum rules. I conclude the discussion on this thread. – EverLearner Jun 20 '23 at 18:10
1

Lisp guy again; here is an Awk program stored in the file gen.awk:

NR == FNR {
  line[++lineno] = $0;
  if (line[lineno - 2] ~ "MATCH LINE")
    rep_line = lineno
  next;
}

{
  outfile = $1
  string = $2

  for (i = 1; i <= lineno; i++) {
    out = line[i]
    if (i == rep_line)
      gsub("NUMBER", string, out)
    print out > outfile
  }
}

Run:

$ rm Out*
$ cat main_file
# stuff before
This is the 'MATCH LINE'
# this is just a comment
This NUMBER to be updated
# stuff after
$ cat ref_file
Out1 ONE
Out2 TWO
Out3 THREE
$ awk -f gen.awk main_file ref_file
$ cat Out1
# stuff before
This is the 'MATCH LINE'
# this is just a comment
This ONE to be updated
# stuff after
$ cat Out2
# stuff before
This is the 'MATCH LINE'
# this is just a comment
This TWO to be updated
# stuff after
$ cat Out3
# stuff before
This is the 'MATCH LINE'
# this is just a comment
This THREE to be updated
# stuff after
Kaz
  • 55,781
  • 9
  • 100
  • 149