web-dev-qa-db-ja.com

UNIXのファイルの最後の文字を削除するにはどうすればよいですか?

任意の複数行テキストファイルがあるとします。

sometext
moretext
lastline

テキストファイルを無効にせずに、ファイルの最後の文字(改行ではなくe)のみを削除するにはどうすればよいですか?

54
MaxPRafferty

より単純なアプローチ(stdoutへの出力、入力ファイルは更新されません):

sed '$ s/.$//' somefile
  • $はSedアドレスで、最後の入力行のみに一致するため、次の関数呼び出し(s/.$//)は最後の行でのみ実行されます。
  • s/.$//は、(この場合last)行の最後の文字を空の文字列に置き換えます。つまり、最後の文字を効果的に削除します。 (改行の前)行。
    .は行の任意の文字に一致し、それに続く$は行の末尾に一致を固定します。この正規表現での$の使用は概念的に関連しているが、以前のSed _としての$の使用とは技術的に異なることに注意してくださいアドレス
  • Stdin入力の例(Bash、Ksh、またはZshを想定):

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

入力ファイルを更新するも(入力ファイルがシンボリックリンクの場合は使用しないでください):

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

注意:
* OSXでは、-i ''だけでなく-iを使用する必要があります。 -iに関連する落とし穴の概要については、 私の答えはここ の下半分を参照してください。
*非常に大きな入力ファイルを処理する必要がある場合やパフォーマンス/ディスク使用量が懸念される場合and使用している場合GNUユーティリティ(Linux )、 sorontarの役立つ回答 を参照してください。

70
mklement0

truncate

truncate -s-1 file

同じファイルの末尾から1文字(-1)を削除します。 >>が同じファイルに追加するのとまったく同じです。

このアプローチの問題は、存在する場合、末尾の改行を保持しないことです。

解決策は次のとおりです。

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

これは、tailが最後のバイト(charではなく)を取るために機能します。

大きなファイルでもほとんど時間はかかりません。

sedではない理由

sed '$ s/.$//' fileのようなsedソリューションの問題は、最初にファイル全体を読み取り(大きなファイルでは長い時間がかかる)、次に(元のファイルと同じサイズの)一時ファイルが必要になることです。

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

そして、一時ファイルを移動してファイルを置き換えます。

39
sorontar

exを使用した別の例を次に示します。これは、sedソリューションほどわかりにくいものではありません。

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

$は最後の行に進み、sは最後の文字を削除し、wqは(viユーザーにとって)よく知られているwrite + quitです。

4
Jens

最終行の最後の文字を削除することが目標である場合、このawkは次のことを行う必要があります。

awk '{a[NR]=$0} END {for (i=1;i<NR;i++) print a[i];sub(/.$/,"",a[NR]);print a[NR]}' file
sometext
moretext
lastlin

すべてのデータを配列に保存してから、出力して最後の行を変更します。

2
Jotne

ただのコメント:sedは一時的にファイルを削除します。そのため、ファイルをテーリングしている場合、tailコマンドを再発行するまで「No such file or directory」という警告が表示されます。

1
Tim Chaubet

編集済みの回答

スクリプトを作成し、デスクトップにテキストを入れました。このテストファイルは「old_file.txt」として保存されます

sometext
moretext
lastline

その後、古いファイルを取得して最終行の最後の文字を削除する小さなスクリプトを作成しました

#!/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'

作成したnew_fileを開くと、次のような出力が表示されました。

sometext
moretext
lastlin

以前の回答をおforびします(注意深く読んでいませんでした)

1
repzero

さまざまな戦略で(そしてsed -iやPerlを避けて)いじくり回した後、私が見つけた最善の方法は次のとおりです。

sed '$! { P; D; }; s/.$//' somefile
1
MaxPRafferty

sed 's/.$//' filename | tee newFilename

これはあなたの仕事をする必要があります。

0
karthik339