2

I am trying to remove all occurrences of 2016/01/30 14:52:51: but the last one. I tried this:

awk '{gsub(//,"2016/01/30 14:52:51: ",$1);print}'

to replace all but the last occurrence with nothing, but that just duplicated 2016/01/30 14:52:51: 4 times with slightly different numbers.

2
  • I'm not sed-savvy enough, but I imagine if you could anchor the last occurrence of the string, you could do a search/replace/branch loop for the initial matches. e.g. search for "(.*)text(.*)text(ending pattern)$", replace with 1 & 3, repeat
    – Jeff Schaller
    Jan 30 '16 at 14:49
  • Are you trying to remove the occurrences in every line or the file. Could you give an example of your input, script and output.
    – jai_s
    Jan 30 '16 at 14:52
3

There is more than one problem with the script, plus the problem statement needs some clarification:

  • the gsub call has the regular expression in the wrong parameter
  • updating $1 has no effect on $0 (the value used in the print statement)
  • OP did not clarify if the intent was to leave the last occurrence on a line untouched, or only the last line containing the date (the latter is more likely).

Here is a script which incorporates those fixes and assumptions:

#!/bin/sh
awk '
BEGIN { row=0; fixup = -1; }
{
    before[row] = $0;
    gsub("2016/01/30 14:52:51: ", "", $0);
    if ( $0 != before[row] ) {
            fixup = row;
    }
    after[row++] = $0;
}
END {
    if (fixup >= 0) {
            after[fixup] = before[fixup];
    }
    for (n = 0; n < row; ++n) {
            print after[n];
    }
}
'

(using two arrays is less efficient, but allows further modification with less effort than without the before array).

I tested this by making an input file (foo.in):

1awk '{gsub(//,"2016/01/30 14:52:51: ",$1);print}'
2awk '{gsub(//,"2016/01/30 14:52:51: ",$1);print}'
3awk '{gsub(//,"2016/01/30 14:52:51: ",$1);print}'
4awk '{gsub(//,"2016/01/30 14:52:51: ",$1);print}'

and running the script like this:

./foo <foo.in

and got

1awk '{gsub(//,"",$1);print}'
2awk '{gsub(//,"",$1);print}'
3awk '{gsub(//,"",$1);print}'
4awk '{gsub(//,"2016/01/30 14:52:51: ",$1);print}'
2
  • I actually didn't understand the script but it was someone who did the same as me and I simply replaced the values with my own. (Also, your answer doesn't seem to work for me, I tried this on a file with only two occurences and it's been running for 20 minutes with nothing happening. (I have restarted and ran again too, so it's not a one time problem). Jan 30 '16 at 15:43
  • You may have not redirected input to awk, e.g., the < character. Also, clarifying your problem with sample input would be helpful. Jan 30 '16 at 16:01
2

My contribution is a POSIX-compliant ed alternative to Thomas Dickey's AWK; it makes the same assumptions:

printf '%s\n' '1;?2016/01/30 14:52:51: ?' '1,.-g//s///' w q | ed filename

ed's ability to traverse the file backwards makes short work of this task.

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.