将读取重定向到输出

时间:2014-01-28 05:20:08

标签: bash command-line posix

我有一段代码用于更改空间描述的数据库的第一部分:

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中,但它似乎不起作用。关于它为什么不起作用的任何想法?

3 个答案:

答案 0 :(得分:2)

执行时

while read -r name rest; do
...
done < commandnames.txt > commandnames.txt

这是发生的事情:

  1. < commandnames.txt:打开“commandnames.txt”进行阅读
  2. > commandnames.txt:打开“commandnames.txt”进行写入并截断它。
  3. while read -r name rest:一次读取一行直到stdin为空
  4. 由于步骤2截断文件,循环运行0次,因此没有什么可写的。因此该文件为空。

    修复很简单:避免在阅读之前删除输入。

    您可以通过写入临时文件,然后在完成后覆盖原始文件来执行此操作:

    while read -r name rest; do
    ...
    done < commandnames.txt > tmpfile && mv tmpfile commandnames.txt
    

答案 1 :(得分:1)

  

然而,> commandnames.txt不起作用,而是清除   文件。

> outfile 截断 1 文件开头。

因此,您尝试从同一文件中读取将不会产生任何结果。

根据需要将输出重定向到其他文件,然后mvcp


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命令以创建临时文件