任意の複数行テキストファイルがあるとします。
sometext
moretext
lastline
テキストファイルを無効にせずに、ファイルの最後の文字(改行ではなくe)のみを削除するにはどうすればよいですか?
より単純なアプローチ(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の役立つ回答 を参照してください。
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
そして、一時ファイルを移動してファイルを置き換えます。
ex
を使用した別の例を次に示します。これは、sedソリューションほどわかりにくいものではありません。
printf '%s\n' '$' 's/.$//' wq | ex somefile
$
は最後の行に進み、s
は最後の文字を削除し、wq
は(viユーザーにとって)よく知られているwrite + quitです。
最終行の最後の文字を削除することが目標である場合、この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
すべてのデータを配列に保存してから、出力して最後の行を変更します。
ただのコメント:sedは一時的にファイルを削除します。そのため、ファイルをテーリングしている場合、tailコマンドを再発行するまで「No such file or directory」という警告が表示されます。
編集済みの回答
スクリプトを作成し、デスクトップにテキストを入れました。このテストファイルは「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びします(注意深く読んでいませんでした)
さまざまな戦略で(そしてsed -iやPerlを避けて)いじくり回した後、私が見つけた最善の方法は次のとおりです。
sed '$! { P; D; }; s/.$//' somefile
sed 's/.$//' filename | tee newFilename
これはあなたの仕事をする必要があります。