[英]Bash scripting: why is the last line missing from this file append?
我正在編寫一個bash腳本,以逐行讀取一組文件並執行一些編輯。 首先,我只是嘗試將文件移至備份位置並按原樣將其寫出,以測試腳本是否正常運行。 但是,它無法復制每個文件的最后一行。 這是代碼段:
while IFS= read -r line
do
echo "Line is ***$line***"
echo "$line" >> $POM
done < $POM.backup
復制文件時,我顯然想保留空格,這就是為什么將IFS設置為null的原因。 從輸出中可以看到正在讀取每個文件的最后一行,但是它從未出現在輸出中。
我還嘗試了另一種變體,它確實打印了最后一行,但在其中添加了換行符:
while IFS= read -r line || [ -n "$line" ]
do
echo "Line is ***$line***"
echo "$line" >> $POM
done < $POM.backup
什么是執行此讀寫操作,以正確的空格完全插入文件且未添加換行符的方式完全寫入文件的最佳方法?
添加換行(LF)的命令不是 read
命令,而是echo
命令。 read
不返回與仍連接在其分隔符行; 相反,它將剝離定界符(也就是說,如果它只是在一行完整的行中出現,那么它將剝離IOW)。
因此,要解決該問題,必須使用echo -n
避免加回定界符,但前提是您的行不完整。
其次,我發現,當提供read
與NAME
(你的情況line
),它TRIMS開頭和結尾的空白,我不認為你想要的。 但這可以通過完全不提供NAME
並使用默認的返回變量REPLY
,它將保留所有空白。
因此,這應該工作:
#!/bin/bash
inFile=in;
outFile=out;
rm -f "$outFile";
rc=0;
while [[ $rc -eq 0 ]]; do
read -r;
rc=$?;
if [[ $rc -eq 0 ]]; then ## complete line
echo "complete=\"$REPLY\"";
echo "$REPLY" >>"$outFile";
elif [[ -n "$REPLY" ]]; then ## incomplete line
echo "incomplete=\"$REPLY\"";
echo -n "$REPLY" >>"$outFile";
fi;
done <"$inFile";
exit 0;
編輯:哇! 查爾斯·達菲(Charles Duffy)的三個出色建議,下面是更新的腳本:
#!/bin/bash
inFile=in;
outFile=out;
while { read -r; rc=$?; [[ $rc -eq 0 || -n "$REPLY" ]]; }; do
if [[ $rc -eq 0 ]]; then ## complete line
echo "complete=\"$REPLY\"";
printf '%s\n' "$REPLY" >&3;
else ## incomplete line
echo "incomplete=\"$REPLY\"";
printf '%s' "$REPLY" >&3;
fi;
done <"$inFile" 3>"$outFile";
exit 0;
如果line不是一行,請添加新行。 像這樣:
while IFS= read -r line
do
echo "Line is ***$line***";
printf '%s' "$line" >&3;
if [[ ${line: -1} != '\n' ]]
then
printf '\n' >&3;
fi
done < $POM.backup 3>$POM
經過審查,我想知道是否:
{
line=
while IFS= read -r line
do
echo "$line"
line=
done
echo -n "$line"
} <$INFILE >$OUTFILE
突出還不夠...
這是我最初的建議:
#!/bin/bash
INFILE=$1
if [[ -z $INFILE ]]
then
echo "[ERROR] missing input file" >&2
exit 2
fi
OUTFILE=$INFILE.processed
# a way to know if last line is complete or not :
lastline=$(tail -n 1 "$INFILE" | wc -l)
if [[ $lastline == 0 ]]
then
echo "[WARNING] last line is incomplete -" >&2
fi
# we add a newline ANYWAY if it was complete, end of file will be seen as ... empty.
echo | cat $INFILE - | {
first=1
while IFS= read -r line
do
if [[ $first == 1 ]]
then
echo "First Line is ***$line***" >&2
first=0
else
echo "Next Line is ***$line***" >&2
echo
fi
echo -n "$line"
done
} > $OUTFILE
if diff $OUTFILE $INFILE
then
echo "[OK]"
exit 0
else
echo "[KO] processed file differs from input"
exit 1
fi
想法是始終在文件末尾添加換行符,並僅在讀取的行之間打印換行符。
給定所有不包含0字節(即\\ 0字符)的文本文件,這應該適用於幾乎所有文本文件,在這種情況下,將丟失0個字符字節。
可以使用初始測試來確定是否可以接受不完整的文本文件。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.