我有一个 bash 脚本,它读取具有多行文本的文件并在这些行上执行命令。有时该命令有效,但有时会失败。我想在命令成功运行的文本行和命令失败的行的开头附加井号 (#),它们应该按原样添加,以便可以在下次运行脚本时重试。从 # 开始的行不会被执行。
我当前的脚本看起来像这样 -
COUNT=1
while read -r LINE; do
if [[ ($LINE != \#*) && !(-z "${LINE// }") ]] ; then
echo "${LINE}"
# execute "$LINE"
if [ $? -eq 0 ]; then
echo OK # Append pound (#) at the start of the line
else
echo FAIL # Keep the line in the source file
fi
fi
COUNT=$(( $COUNT + 1 ))
done < $SRC_FILE
正如您所看到的,条件已经存在,我只需要替换这些条件echo OK
和echo FAIL
代码行即可。我试过这个答案,但它最终删除了所有行,我不希望这样,我想将失败的行保留在文件中。
我尝试使用sed
,但它似乎什么也没做 -
sed -n "${COUNT}s/^/#/" $SRC_FILE >> $SRC_FILE
有什么办法可以做到这一点吗?
PS:我想让它在 Linux 和 Mac 终端上的 bash 和 zsh 上运行,尤其是 Mac zsh。
更新:
我尝试了以下命令
sed "${COUNT}s/.*/#&/" $SRC_FILE >$SRC_FILE
它从源文件中删除所有行并将其设为空,但如果我更改输出文件,它会起作用,尽管仅在最后一行添加 # ,因为它仍然从原始源文件中读取。
答案1
你可以这样做:
#! /bin/sh -
src_file=/path/to/file
{
while read <&3 -r line; do
case $line in
('#'*) ;;
(*)
if eval " $line" 3<&- 4>&-; then
echo OK
line="# $line"
else
echo FAIL
fi
esac
printf '%s\n' "$line" >&4
done
mv -- "$src_file.new" "$src_file"
} 3< "$src_file" 4> "$src_file.new"
文件的每一行都将被评估为sh
代码。如果这些行使用-特定或-特定功能,请替换sh
为bash
或。zsh
bash
zsh
在这里,我们生成一个文件,最后将file.new
其重命名。 (GNU) 或(FreeBSD/macOS)file
或多或少也是这么做的。通常,您无法在读取给定文件的同时轻松写入该文件。sed -i
sed -i ''
答案2
sed [command] file > file
正如你所发现的,使用意志并不能做你想做的事。重定向会清除 的内容file
并将其替换为 的输出sed
。
您需要做的是使用 的sed
内置功能就地修改文件:
sed --in-place "$COUNTs/^/#/" file