我有一段代码用于更改空间描述的数据库的第一部分:
if [[ "$(cut -d ' ' -f 1 commandnames.txt | grep -F "$2")" == "" ]] ; then
while read -r name rest; do
if [[ "$1" == "$name" ]]
then echo "$2 $rest"
else echo "$name $rest"; fi
done < commandnames.txt > commandnames.txt
echo "Renamed $1 to $2."
fi
但是,> commandnames.txt
不起作用,而是清除文件。当输出为stdout时,它工作正常。我尝试将while
循环放到stdout重定向到子shell中,但它似乎不起作用。关于它为什么不起作用的任何想法?
答案 0 :(得分:2)
执行时
while read -r name rest; do
...
done < commandnames.txt > commandnames.txt
这是发生的事情:
< commandnames.txt
:打开“commandnames.txt”进行阅读> commandnames.txt
:打开“commandnames.txt”进行写入并截断它。while read -r name rest
:一次读取一行直到stdin为空由于步骤2截断文件,循环运行0次,因此没有什么可写的。因此该文件为空。
修复很简单:避免在阅读之前删除输入。
您可以通过写入临时文件,然后在完成后覆盖原始文件来执行此操作:
while read -r name rest; do
...
done < commandnames.txt > tmpfile && mv tmpfile commandnames.txt
答案 1 :(得分:1)
然而,
> commandnames.txt
不起作用,而是清除 文件。
说> outfile
截断 1 文件开头。
因此,您尝试从同一文件中读取将不会产生任何结果。
根据需要将输出重定向到其他文件,然后mv
或cp
。
1 引自manual(强调我的):
输出的重定向导致名称来自的文件 扩展要在文件描述符 n 上写入的单词,或者 如果未指定 n ,则为标准输出(文件描述符1)。如果 文件不存在它被创建; 如果确实存在,则将其截断为 零大小。
答案 2 :(得分:1)
如果没有某种临时存储,你就无法做到这一点。
如果你100%确定你的commandnames.txt文件不会太大,你可以将文件读入一个变量,然后解析变量的内容
GV_LINES=$(cat test_lines.txt)
while read LV_LINE
do
echo "${LV_LINE}_suffix"
done <<< "${GV_LINES}" > test_lines.txt
否则请查看mktemp或tempfile命令以创建临时文件