How can I remove the last character of a file in unix?

前端 未结 8 1327
眼角桃花
眼角桃花 2020-11-30 05:35

Say I have some arbitrary multi-line text file:

sometext
moretext
lastline

How can I remove only the last character (the e, not the newline

相关标签:
8条回答
  • 2020-11-30 05:42

    EDITED ANSWER

    I created a script and put your text inside on my Desktop. this test file is saved as "old_file.txt"

    sometext
    moretext
    lastline
    

    Afterwards I wrote a small script to take the old file and eliminate the last character in the last line

    #!/bin/bash
    no_of_new_line_characters=`wc  '/root/Desktop/old_file.txt'|cut -d ' ' -f2`
    let "no_of_lines=no_of_new_line_characters+1"
    sed -n 1,"$no_of_new_line_characters"p  '/root/Desktop/old_file.txt' > '/root/Desktop/my_new_file'
    sed -n "$no_of_lines","$no_of_lines"p '/root/Desktop/old_file.txt'|sed 's/.$//g' >> '/root/Desktop/my_new_file'
    

    opening the new_file I created, showed the output as follows:

    sometext
    moretext
    lastlin
    

    I apologize for my previous answer (wasn't reading carefully)

    0 讨论(0)
  • 2020-11-30 05:43

    truncate

    truncate -s-1 file
    

    Removes one (-1) character from the end of the same file. Exactly as a >> will append to the same file.

    The problem with this approach is that it doesn't retain a trailing newline if it existed.

    The solution is:

    if     [ -n "$(tail -c1 file)" ]    # if the file has not a trailing new line.
    then
           truncate -s-1 file           # remove one char as the question request.
    else
           truncate -s-2 file           # remove the last two characters
           echo "" >> file              # add the trailing new line back
    fi
    

    This works because tail takes the last byte (not char).

    It takes almost no time even with big files.

    Why not sed

    The problem with a sed solution like sed '$ s/.$//' file is that it reads the whole file first (taking a long time with large files), then you need a temporary file (of the same size as the original):

    sed '$ s/.$//' file  > tempfile
    rm file; mv tempfile file
    

    And then move the tempfile to replace the file.

    0 讨论(0)
  • 2020-11-30 05:44

    Just a remark: sed will temporarily remove the file. So if you are tailing the file, you'll get a "No such file or directory" warning until you reissue the tail command.

    0 讨论(0)
  • 2020-11-30 05:47

    After a whole bunch of playing around with different strategies (and avoiding sed -i or perl), the best way i found to do this was with:

    sed '$! { P; D; }; s/.$//' somefile
    
    0 讨论(0)
  • A simpler approach (outputs to stdout, doesn't update the input file):

    sed '$ s/.$//' somefile
    
    • $ is a Sed address that matches the last input line only, thus causing the following function call (s/.$//) to be executed on the last line only.
    • s/.$// replaces the last character on the (in this case last) line with an empty string; i.e., effectively removes the last char. (before the newline) on the line.
      . matches any character on the line, and following it with $ anchors the match to the end of the line; note how the use of $ in this regular expression is conceptually related, but technically distinct from the previous use of $ as a Sed address.
    • Example with stdin input (assumes Bash, Ksh, or Zsh):

      $ sed '$ s/.$//' <<< $'line one\nline two'
      line one
      line tw
      

    To update the input file too (do not use if the input file is a symlink):

    sed -i '$ s/.$//' somefile
    

    Note:
    * On OSX, you'd have to use -i '' instead of just -i; for an overview of the pitfalls associated with -i, see the bottom half of my answer here.
    * If you need to process very large input files and/or performance / disk usage are a concern and you're using GNU utilities (Linux), see sorontar's helpful answer.

    0 讨论(0)
  • 2020-11-30 05:50

    Here's another using ex, which I find not as cryptic as the sed solution:

     printf '%s\n' '$' 's/.$//' wq | ex somefile
    

    The $ goes to the last line, the s deletes the last character, and wq is the well known (to vi users) write+quit.

    0 讨论(0)
提交回复
热议问题