3

we want to add the following lines in log4j file

log4j.appender.DRFA=org.apache.log4j.RollingFileAppender
log4j.appender.DRFA.MaxBackupIndex=100
log4j.appender.DRFA.MaxFileSize=10MB

but these lines must be before the first line that include the word - DatePattern , and no matter if line is with mark or not

#log4j.appender.DRFA.DatePattern=.yyyy-MM-dd

or

log4j.appender.DRFA.DatePattern=.yyyy-MM-dd

note - in case DatePattern word apears couple times in file , then the three lines must be set only before the first line that include - DatePattern

example 1 ( expected output )

log4j.appender.DRFA=org.apache.log4j.RollingFileAppender
log4j.appender.DRFA.MaxBackupIndex=100
log4j.appender.DRFA.MaxFileSize=10MB


#log4j.appender.DRFA.DatePattern=.yyyy-MM-dd

example 2 ( expected output )

log4j.appender.DRFA=org.apache.log4j.RollingFileAppender
log4j.appender.DRFA.MaxBackupIndex=100
log4j.appender.DRFA.MaxFileSize=10MB


log4j.appender.DRFA.DatePattern=.yyyy-MM-dd
4

If I understand your question correctly you merely want to replace this line:

log4j.appender.DRFA.DatePattern=.yyyy-MM-dd
-or-
#log4j.appender.DRFA.DatePattern=.yyyy-MM-dd

With these lines:

log4j.appender.DRFA=org.apache.log4j.RollingFileAppender
log4j.appender.DRFA.MaxBackupIndex=100
log4j.appender.DRFA.MaxFileSize=10MB
log4j.appender.DRFA.DatePattern=.yyyy-MM-dd
-or-
#log4j.appender.DRFA.DatePattern=.yyyy-MM-dd

This GNU sed command can do this:

$ sed -i 's/\(.*appender.DRFA.DatePattern=.*\)/log4j.appender.DRFA=org.apache.log4j.RollingFileAppender\nlog4j.appender.DRFA.MaxBackupIndex=100\nlog4j.appender.DRFA.MaxFileSize=10MB\n\n\n\1/' log4j.properties

With respect to the duplicating of lines. You're not going to have this appender defined more than 1 time:

appender.DRFA.DatePattern

Therefore we can look more explicitly for this occurrence, rather than the DatePattern line that you're looking for.

Example run

Here's a sample file that has just this line in it:

$ cat log4j.properties
#log4j.appender.DRFA.DatePattern=.yyyy-MM-dd

Run the sed command above against this file:

$ cat log4j.properties
log4j.appender.DRFA=org.apache.log4j.RollingFileAppender
log4j.appender.DRFA.MaxBackupIndex=100
log4j.appender.DRFA.MaxFileSize=10MB
#log4j.appender.DRFA.DatePattern=.yyyy-MM-dd
  • 1
    @yael - I updated the answer so that it includes them now. – slm Aug 5 '18 at 18:16
5

Using awk:

awk 'done != 1 && /DatePattern/ {
    print "log4j.appender.DRFA=org.apache.log4j.RollingFileAppender"
    print "log4j.appender.DRFA.MaxBackupIndex=100"
    print "log4j.appender.DRFA.MaxFileSize=10MB"
    done = 1
    } 1' file >newfile && mv newfile file

This would print the three lines when the first match of DatePattern occurs in the file. The flag done is then set to 1 which stops the lines from being printed again. The trailing 1 at the very end causes every line in the in-data to be printed.

If you want empty lines in the output after the three lines, add \n\n to the end of the last string.

The output is written to newfile and if awk did not encounter any strange errors, the original is then replaced by this once the awk process terminates.


Requested in comments: Adding the lines after the matched line,

awk '1; done != 1 && /DatePattern/ {
    print "log4j.appender.DRFA=org.apache.log4j.RollingFileAppender"
    print "log4j.appender.DRFA.MaxBackupIndex=100"
    print "log4j.appender.DRFA.MaxFileSize=10MB"
    done = 1
    }' file

This moves the 1 (which does the printing of each input line and could be replaced by { print }) to before the code that is triggered when the pattern matches.

  • good solution , but I prefer to update the file itself like "sed -i" and not copy the file to the source file for update , is it possible with awk ? – yael Aug 5 '18 at 17:43
  • @yael A standard redirection and mv. See updated answer. Not even GNU awk has an in-place editing option. It's not something that awk program usually do. – Kusalananda Aug 5 '18 at 17:45
  • 1
    GNU awk has it... – don_crissti Aug 5 '18 at 18:00
  • @don_crissti :-) That's an extension, even to GNU awk. – Kusalananda Aug 5 '18 at 18:03
  • 1
    Sure but that doesn't change the fact that it exists... Anyway, +1 for answering the actual question here... – don_crissti Aug 5 '18 at 18:22
4

Using GNU sed you may approach it this way also:

sed -i -e '
    /DatePattern/!b

    i\
log4j.appender.DRFA=org.apache.log4j.RollingFileAppender\
log4j.appender.DRFA.MaxBackupIndex=100\
log4j.appender.DRFA.MaxFileSize=10MB

    :a;n;$!ba
' input.file

And if you are sure that the DatePattern cannot be on the last line of the file, then you could do this also:

sed -i -e '
    /DatePattern/!b
    r file2add.txt
    N;:a;n;$!ba
' input.file

where you put all the lines to be added into a file, say file2add.txt. Note: with this method, you don't put trailing backslashes in the file file2add.txt.

  • Yes, those are both proper ways to do it with sed. Future visitors should keep in mind that i requires any embedded backslashes to be escaped. – don_crissti Aug 5 '18 at 18:32
  • And that the empty label and ; concatenation are GNU extensions to sed. – Toby Speight Aug 6 '18 at 9:37
  • @TobySpeight - empty label is specified by POSIX: "b [label] Branch to the : command verb bearing the label argument. If label is not specified, branch to the end of the script". Some commands can also be concatenated via ; per the same standard: "Editing commands other than {...}, a, b, c, i, r, t, w, :, and # can be followed by a <semicolon>, optional <blank> characters, and another editing command." – don_crissti Aug 6 '18 at 12:32
  • Thanks for the correction (I note that : is among the commands that can't be joined with a subsequent command, so I turned out to be slightly correct by accident!) – Toby Speight Aug 6 '18 at 12:42
2

Since you tagged this query with perl also, so here goes one obvious way:

perl -pi -e '
     print <<\EOF if /DatePattern/ && !$seen++;
log4j.appender.DRFA=org.apache.log4j.RollingFileAppender
log4j.appender.DRFA.MaxBackupIndex=100
log4j.appender.DRFA.MaxFileSize=10MB
EOF
' input.file

Note: The added text mustn't contain the standalone string EOF on a line by itself. The backslashing of the heredoc is necessary , lest any variables get expanded .

If you cannot be sure of the above constraints in the text to add, then do this:

perl -pi -e '
    next if !/DatePattern/ || $seen++;
    open my $fh, "<", "file2add.txt" or die "Could not open file for reading:$!\n";
    $_ = join "", <$fh>, $_;
' input.file
1

This is a job well-suited to ed, the standard file editor:

/DatePattern/i
log4j.appender.DRFA=org.apache.log4j.RollingFileAppender
log4j.appender.DRFA.MaxBackupIndex=100
log4j.appender.DRFA.MaxFileSize=10MB
.
wq

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.