[英]Remove the last line from a file in Bash
我有一個文件foo.txt
,其中包含以下幾行:
a
b
c
我想要一個簡單的命令,導致foo.txt
的內容是:
a
b
使用GNU sed
:
sed -i '$ d' foo.txt
-i
選項在 3.95 之前的GNU sed
版本中不存在,因此您必須將其用作帶有臨時文件的過濾器:
cp foo.txt foo.txt.tmp
sed '$ d' foo.txt.tmp > foo.txt
rm -f foo.txt.tmp
當然,在這種情況下,您也可以使用head -n -1
而不是sed
。
操作系統:
在 Mac OS X(從 10.7.4 開始)上,相當於上面的sed -i
命令是
sed -i '' -e '$ d' foo.txt
這是迄今為止最快和最簡單的解決方案,尤其是在大文件上:
head -n -1 foo.txt > temp.txt ; mv temp.txt foo.txt
如果要刪除頂行,請使用以下命令:
tail -n +2 foo.txt
這意味着從第 2 行開始的輸出行。
不要使用sed
從文件的頂部或底部刪除行——如果文件很大,它會非常慢。
我在這里的所有答案都遇到了麻煩,因為我正在處理一個巨大的文件(~300Gb)並且沒有一個解決方案可以擴展。 這是我的解決方案:
filename="example.txt"
file_size="$(stat --format=%s "$filename")"
trim_count="$(tail -n1 "$filename" | wc -c)"
end_position="$(echo "$file_size - $trim_count" | bc)"
dd if=/dev/null of="$filename" bs=1 seek="$end_position"
或者,作為單襯:
dd if=/dev/null of=<filename> bs=1 seek=$(echo $(stat --format=%s <filename> ) - $( tail -n1 <filename> | wc -c) | bc )
用字詞:找出您想要結束的文件的長度(文件的長度減去其最后一行的長度,使用bc
),並將該位置設置為文件的末尾(通過dd
ing 一個字節/dev/null
到它)。
這很快,因為tail
從末尾開始讀取,而dd
將覆蓋文件原地,而不是復制(和解析)文件的每一行,這是其他解決方案所做的。
注意:這會從文件中刪除該行! 在您自己的文件上嘗試之前,請先備份或測試一個虛擬文件!
要從文件中刪除最后一行而不讀取整個文件或重寫任何內容,您可以使用
tail -n 1 "$file" | wc -c | xargs -I {} truncate "$file" -s -{}
要刪除最后一行並將其打印在標准輸出上(“彈出”它),您可以將該命令與tee
結合使用:
tail -n 1 "$file" | tee >(wc -c | xargs -I {} truncate "$file" -s -{})
這些命令可以有效地處理非常大的文件。 這類似於 Yossi 的回答並受到其啟發,但它避免了使用一些額外的功能。
如果您要重復使用這些並想要錯誤處理和一些其他功能,您可以在此處使用poptail
命令: https : //github.com/donm/evenmoreutils
在 Mac 上, head -n -1 不起作用。 而且,我試圖找到一個簡單的解決方案 [無需擔心處理時間] 僅使用“head”和/或“tail”命令來解決這個問題。
我嘗試了以下命令序列,很高興我可以只使用“tail”命令 [ 使用 Mac 上可用的選項 ] 來解決它。 所以,如果你在 Mac 上,並且只想使用“tail”來解決這個問題,你可以使用這個命令:
貓文件.txt | 尾巴 -r | 尾 -n +2 | 尾-r
1> tail -r :簡單地顛倒其輸入中的行順序
2> tail -n +2 :這將打印從其輸入中的第二行開始的所有行
Mac 用戶
如果您只想刪除最后一行的輸出而不更改文件本身
sed -e '$ d' foo.txt
如果要刪除輸入文件本身的最后一行,請執行
sed -i '' -e '$ d' foo.txt
echo -e '$d\nw\nq'| ed foo.txt
awk 'NR>1{print buf}{buf = $0}'
本質上,這段代碼說明如下:
對於第一行之后的每一行,打印緩沖行
對於每一行,重置緩沖區
緩沖區滯后一行,因此您最終會打印第 1 到 n-1 行
sed '$d' ~/path/to/your/file/name
sed -i '' -e '$ d' ~/path/to/your/file/name
awk "NR != `wc -l < text.file`" text.file &> newtext.file
這個片段可以解決問題。
這兩種解決方案都以其他形式存在。 我發現這些更實用、更清晰、更有用:
使用 dd:
BADLINESCOUNT=1
ORIGINALFILE=/tmp/whatever
dd if=${ORIGINALFILE} of=${ORIGINALFILE}.tmp status=none bs=1 count=$(printf "$(stat --format=%s ${ORIGINALFILE}) - $(tail -n${BADLINESCOUNT} ${ORIGINALFILE} | wc -c)\n" | bc )
/bin/mv -f ${ORIGINALFILE}.tmp ${ORIGINALFILE}
使用截斷:
BADLINESCOUNT=1
ORIGINALFILE=/tmp/whatever
truncate -s $(printf "$(stat --format=%s ${ORIGINALFILE}) - $(tail -n${BADLINESCOUNT} ${ORIGINALFILE} | wc -c)\n" | bc ) ${ORIGINALFILE}
以下是您可以手動執行的方法(當我需要快速刪除文件中的最后一行時,我個人經常使用此方法):
vim + [FILE]
那里的+
號表示在 vim 文本編輯器中打開文件時,光標將定位在文件的最后一行。
現在只需在鍵盤上按d
兩次即可。 這將完全符合您的要求——刪除最后一行。 之后,按:
然后按x
然后按Enter
。 這將保存更改並使您返回到 shell。 現在,最后一行已成功刪除。
您也可以嘗試此方法:刪除最后 n 行的示例。
a=0; while [ $a -lt 4 ]; do sed -i '$ d' output.txt; a=
expr $a + 1
;完成
從文件(output.txt)中刪除最后 4 行。
可以處理大量數據並且輸出還可以,但是有一條垃圾線。
如果我將腳本的輸出通過管道傳輸到:
| sed -i '$ d' 我會得到以下錯誤,最后根本沒有輸出 sed: no input files
但是| head -n -1 有效!
紅寶石(1.9+)
ruby -ne 'BEGIN{prv=""};print prv ; prv=$_;' file
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.