我有一個包含多行的檔案(log.txt)。
Uploaded 1Y3JxCDpjsId_f8C7YAGAjvHHk-y-QVQM at 1.9 MB/s, total 3.9 MB
Uploaded 14v58hwKP457ZF32rwIaUFH216yrp9fAB at 317.3 KB/s, total 2.1 MB
log.txt 中的每一行代表一個需要洗掉的檔案。我想洗掉檔案,然后洗掉相應的行。
例子:
rm 1Y3JxCDpjsId_f8C7YAGAjvHHk-y-QVQM
并在洗掉 log.txt 包含的檔案后,洗掉該行,只留下其他行。
Uploaded 14v58hwKP457ZF32rwIaUFH216yrp9fAB at 317.3 KB/s, total 2.1 MB
uj5u.com熱心網友回復:
嘗試這個:
#!/bin/bash
logfile="logfile.txt"
logfilecopy=$( mktemp )
cp "$logfile" "$logfilecopy"
while IFS= read -r line
do
filename=$( echo "$line" | sed 's/Uploaded \(.*\) at .*/\1/' )
if [[ -f "$filename" ]]
then
tempfile=$( mktemp )
rm -f "$filename" && grep -v "$line" "$logfile" >"$tempfile" && mv "$tempfile" "$logfile"
fi
done < "$logfilecopy"
# Cleanup
rm -f "$logfilecopy"
它確實:
- 保留原始日志檔案的副本。
while使用and讀取此副本的每一行read。- 對于每一行,提取檔案名。請注意,
sed由于檔案名可能包含空格,因此已完成。因此cut不能按要求作業。 - 如果檔案存在,則洗掉它,從日志檔案中洗掉該行并將其存盤在臨時檔案中,將臨時檔案移動到日志檔案中。
- 最后一步是
&&在命令之間完成的,以確保在繼續之前完成最后一個命令。如果rm失敗,則不得洗掉日志條目。 - 最后洗掉原來的日志檔案副本。
- 如果需要,您可以添加
echo陳述句 and-or-xto$!/bin/bash進行除錯。
uj5u.com熱心網友回復:
以下代碼log.txt逐行讀取,使用 bash ERE 捕獲檔案名并嘗試洗掉該檔案。當正則運算式或洗掉失敗時,它會輸出原始行。
#!/bin/bash
tmpfile=$( mktemp ) || exit 1
while IFS='' read -r line
do
[[ $line =~ ^Uploaded\ (.*)\ at ]] &&
rm -- "${BASH_REMATCH[1]}" ||
echo "$line"
done < log.txt > "$tmpfile" &&
mv "$tmpfile" log.txt
備注:while回圈的最終結果是true除非讀取log.txt或生成有問題,因此將with"$tmpfile"鏈接起來,這樣您就不會濫用覆寫原始日志檔案。mv&&
uj5u.com熱心網友回復:
另一種使用bash4 GNU 工具的方法。
#!/usr/bin/env bash
##: Save the file names in an array named files using mapfile aka readarray.
##: Process Substitution and With GNU grep that supports the -P flag.
mapfile -t files < <(grep -Po '(?<=Uploaded ).*(?= at)' log.txt)
##: loop through the files ("${files[@]}") and check if it is existing (-e).
##: If it does, save them in an array named existing_file.
##: Add an additional test if need be, see "help test".
for f in "${files[@]}"; do
[[ -e $f ]] && existing_file =("$f")
done
##: Format the array existing_file into a syntax that is accepted
##: by GNU sed, e.g. "/file1|file2|file3|file4/d" and save it
##: in a variable named to_delete.
to_delete=$(IFS='|'; printf '%s' "/${existing_file[*]}/d")
##: delete/remove the existing files.
##: Not sure if ARG_MAX will come up.
echo rm -v -- "${existing_file[@]}"
##: Remove the deleted files (lines that contains the file name)
##: from log.txt using GNU sed.
echo sed -E -i "$to_delete" log.txt
echo如果您對輸出感到滿意,請洗掉所有內容。這不完全符合您的要求,也不完美,但它可能正是您所需要的。
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/503769.html
