SED: insert something after the second last line?

sed
12,186

Solution 1

To insert a line before the last ($) one:

$ cat test
one
two
three
four
five

$ sed '$i<hello>!' test
one
two
three
four
<hello>!
five

That's for GNU sed (and beware leading spaces or tabs are stripped). Portably (or with GNU sed, if you want to preserve the leading spaces or tabs in the inserted line), you'd need:

sed '$i\
<hello>!' test

Solution 2

Yes, sed can be told to act on only a specific line by writing the line number before the operation you tell it to perform. For example, to insert a line with the string foo after the 4th line of a file, you could do:

sed '4s/$/\nfoo/' file  # GNU sed and a few others
sed '4s/$/\
foo/' file # standardly/portably

To insert a line after the next to last line, I can think of two approaches:

  1. Count the number of lines first and then make the edit:

    sed "$(( $( wc -l < file) -2 ))s/$/\nfoo/" file
    
  2. Use tac:

    tac file | sed '2s/$/\nfoo/' | tac
    
Share:
12,186

Related videos on Youtube

Fractaliste
Author by

Fractaliste

French IT engineer. Prefered language : Java Prefered framework : Laravel Prefered solver : Choco Prefered metasyntactic variable : plop Prefered quote : There are 10 kind of people on the world, those who understand binary, and those who don't. If needed, you can contact me on : fractaliste at gmail dot com

Updated on September 18, 2022

Comments

  • Fractaliste
    Fractaliste over 1 year

    In a XML configuration file I need to add a line, in order to not to break the last closing tag. Is it possible to do it with SED ?

    The number of line of the whole file can change from a server to another...

    Edit : Some exemple of file I need to edit :

    <configuration>
    
      <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <!-- encoders are assigned the type
             ch.qos.logback.classic.encoder.PatternLayoutEncoder by default -->
        <encoder>
          <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
        </encoder>
      </appender>
    
      <root level="debug">
        <appender-ref ref="STDOUT" />
      </root>
    </configuration>
    

    An other exemple:

      <?xml version="1.0" encoding="UTF-8"?>
      <configuration>
    
        <property name="DEV_HOME" value="c:/logs" />
    
        <appender name="FILE-AUDIT"
          class="ch.qos.logback.core.rolling.RollingFileAppender">
          <file>${DEV_HOME}/debug.log</file>
          <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <Pattern>
              %d{yyyy-MM-dd HH:mm:ss} - %msg%n
            </Pattern>
          </encoder>
    
          <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- rollover daily -->
            <fileNamePattern>${DEV_HOME}/archived/debug.%d{yyyy-MM-dd}.%i.log
                              </fileNamePattern>
            <timeBasedFileNamingAndTriggeringPolicy
              class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
              <maxFileSize>10MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
          </rollingPolicy>
    
        </appender>
    
        <logger name="com.mkyong.web" level="debug"
          additivity="false">
          <appender-ref ref="FILE-AUDIT" />
        </logger>
    
        <root level="error">
          <appender-ref ref="FILE-AUDIT" />
        </root>
    
        <logger name="com.mkyong.ext" level="debug"
          additivity="false">
          <appender-ref ref="FILE-AUDIT" />
        </logger>
    
          <logger name="com.mkyong.other" level="info"
          additivity="false">
          <appender-ref ref="FILE-AUDIT" />
        </logger>
    
          <logger name="com.mkyong.commons" level="debug"
          additivity="false">
          <appender-ref ref="FILE-AUDIT" />
        </logger>
      </configuration>
    
    • Fractaliste
      Fractaliste about 7 years
      @StephenKitt You're right but I need tools included with Ubuntu12 because I can't install new tools on the server.
    • don_crissti
      don_crissti about 7 years
      What a mess... Could you perhaps post a very short input sample and the expected output ?
    • Kusalananda
      Kusalananda about 7 years
      Why can't you install tools on the server?
    • Fractaliste
      Fractaliste about 7 years
      @Kusalananda it's a secured environment and each tools to be installed have to be tested and validated by a dedicated team. It's more a corporate's process problen than an inability to install it.
    • Stephen Kitt
      Stephen Kitt about 7 years
      And yet you’re allowed to manipulate Log4J XML files directly on the server? O_O
    • Kusalananda
      Kusalananda about 7 years
      Notice that any script that comes out of here may be considered a tool that needs to be tested and validated too. Just saying.
  • Fractaliste
    Fractaliste about 7 years
    As far as I understand I can't use the sed's -i option with tac?
  • terdon
    terdon about 7 years
    @Fractaliste no, not with tac, but you can always do tac file | sed '2s/$/\nfoo/' | tac > newfile && mv newfile file
  • Stéphane Chazelas
    Stéphane Chazelas about 7 years
    You just sed '$s/^/foo\n/' to insert before the last one.
  • terdon
    terdon about 7 years
    @StéphaneChazelas yes, I know that now, after reading Kamaraj's answer, but I wasn't aware of that when I posted mine.
  • ACK_stoverflow
    ACK_stoverflow about 2 years
    For anyone who, like me, is trying to insert a leading tab with this solution and running into problems (perhaps because I'm using sed from busybox?) the following works: sed -e '$i \' -e $'\t'"scan_ssid=1" /tmp/connect.conf