Add a newline only if it doesn't exist

前端 未结 8 601
温柔的废话
温柔的废话 2021-01-31 08:49

I want to add a newline at the end of a file only if it doesn\'t exists, this is to prevent multiple newlines at the end of the file.

I\'m hoping to use sed. Here\'s the

相关标签:
8条回答
  • 2021-01-31 08:57

    Using Bash only

    You can use Command Substitution (remove trailing newlines) with Here Strings (appends newline):

       Command Substitution
           Command substitution allows the output of a command to replace the command  name.   There  are  two
           forms:
    
              $(command)
           or
              `command`
    
           Bash  performs  the expansion by executing command in a subshell environment and replacing the com-
           mand substitution with the standard output of the command,  with  any  trailing  newlines  deleted.
           Embedded newlines are not deleted, but they may be removed during word splitting.  The command sub-
           stitution $(cat file) can be replaced by the equivalent but faster $(< file).
    
    
    
       Here Strings
           A variant of here documents, the format is:
    
              [n]<<<word
    
           The word undergoes brace expansion, tilde expansion, parameter and variable expansion, command sub-
           stitution,  arithmetic expansion, and quote removal.  Pathname expansion and word splitting are not
           performed.  The result is supplied as a single string, with a newline appended, to the  command  on
           its standard input (or file descriptor n if n is specified).
    

    Here's how it works:

    cat <<<"$(<inputfile)"
    

    Output to file:

    cat <<<"$(<inputfile)" >outputfile
    

    If you need inputfile and outputfile to be the same file name, you have a couple options - use sponge command, save to temporary variable with more command substitution, or save to temporary file.


    Using Sed

    Others have suggested using

    sed '$a\' inputfile
    

    which appends nothing to the last line. This is fine, but I think

    sed '$q' inputfile
    

    is a bit clearer, because it quits on the last line. Or you can do

    sed -n 'p'
    

    which uses -n to suppress output, but prints it back out with p.

    In any of these cases, sed will fix up the line and add a newline, at least for GNU and BSD sed. However, I'm not sure if this functionality is defined by POSIX. A version of sed might just skip your line without a newline since a line is defined as

    A sequence of zero or more non- characters plus a terminating character.

    0 讨论(0)
  • 2021-01-31 08:58

    Using awk :

    awk '/^$/{f=1}END{ if (!f) {print "\r"}}1' inputfile
    

    Match blank line ^$(just like you did) and set up a flag. If flag is not set at the end, place newline character.

    Note: that \r is in OS X. Use \n for other.

    0 讨论(0)
  • 2021-01-31 09:01
    tail -c1 file | read -r _ || echo >> file
    

    gets the last character of the file pipes it into read, which will exit with a nonzero exit code if it encounters EOF before newline (so, if the last character of the file isn't a newline). If read exits nonzero, then append a newline onto the file using echo (if read exits 0, that satisfies the ||, so the echo command isn't run).

    From http://backreference.org/2010/05/23/sanitizing-files-with-no-trailing-newline/.

    0 讨论(0)
  • 2021-01-31 09:04

    sed

    GNU:

    sed -i '$a\' *.txt
    

    OS X:

    sed -i '' '$a\' *.txt
    

    $ addresses the last line. a\ is the append function.

    OS X's sed

    sed -i '' -n p *.txt
    

    -n disables printing and p prints the pattern space. p adds a missing newline in OS X's sed but not in GNU sed, so this doesn't work with GNU sed.

    awk

    awk 1
    

    1 can be replaced with anything that evaluates to true. Modifying a file in place:

    { rm file;awk 1 >file; }<file
    

    bash

    [[ $(tail -c1 file) && -f file ]]&&echo ''>>file
    

    Trailing newlines are removed from the result of the command substitution, so $(tail -c1 file) is empty only if file ends with a linefeed or is empty. -f file is false if file is empty. [[ $x ]] is equivalent to [[ -n $x ]] in bash.

    0 讨论(0)
  • 2021-01-31 09:10

    I solved this task by using dos2unix (or counterparts) with the --newline flag. The advantage is that these tools detect binary files on their own. I like the solution with tail -c1 but filtering binary files beforehand has been really slow for me.

    dos2unix --newline my_file.txt
    

    Eventually I wrote a script that searched my project directory, converted all files to LF (dos2unix) except *.cmd files (CRLF, unix2dos) and used the flag to get the newlines right with one call.

    0 讨论(0)
  • 2021-01-31 09:13

    Rather than processing the whole file with see just to add a newline at the end, just check the last character and if it's not a newline, append one. Testing for newline is slightly interesting, since the shell will generally trim them from the end of strings, so I append "x" to protect it:

    if [ "$(tail -c1 "$inputfile"; echo x)" != $'\nx' ]; then
        echo "" >>"$inputfile"
    fi
    

    Note that this will append newline to empty files, which might not be what you want. If you want to leave empty files alone, add another test:

    if [ -s "$inputfile" ] && [ "$(tail -c1 "$inputfile"; echo x)" != $'\nx' ]; then
        echo "" >>"$inputfile"
    fi
    
    0 讨论(0)
提交回复
热议问题