2014-08-30 61 views
0

我知道下面的选项将输出追加到文件:重定向Python脚本的输出到文件的开头

test.py:

print "Error" 
print "Warning" 

的test.txt:

Levels: 
Debug 

当我这样做:

python test.py > test.txt 

它附加在文件的末尾。

但是,如果我想在一个文件的开头追加,让自己的文件的输出看起来如下:

Levels: 
Error 
Warning 
Debug 

是否有这样做的任何直接的方式可能没有手动创建临时文件(例如sed -i可以)。

我尝试了好几种方法SED:

sed -i '1i\`python test.py`' test.txt 

但没有似乎是工作。

+0

为什么你需要追加到文件的开头?据我所知,没有操作系统允许你追加到文件的开头。也许找到一种方法可能会更好,所以你不必追加到文件的开头。 – Dunes 2014-08-30 13:06:52

+0

您可以在没有任何tmp文件的情况下执行此操作(例如,请参阅http://stackoverflow.com/a/17331179/1745001),但不能以任何方式直截了当。 – 2014-08-30 14:10:18

+0

为了安全起见,您*希望*使用临时文件。重命名文件是原子性的,有效地允许您在一个不可中断的步骤中用新的文件替换旧文件:如果移动失败,原始文件仍然完好无损。链接的答案会尝试将数据写入原始位置,这意味着如果中途出于任何原因写入失败,则原始文件已损坏。 – chepner 2014-09-01 12:20:29

回答

1

一个简单的方法做,这是使用一个单独的,临时文件:

python test.py | cat - test.txt > tmp && mv tmp test.txt 

-意味着cat使用标准输入。


我刚才意识到你实际上想把文本放在第一行之后,而不是在开头。要做到这一点,你可以用awk:

python test.py | awk 'NR==FNR{a[++n]=$0;next}1;/Levels:/{for(i=1;i<=n;++i)print a[i]}' - test.txt 

NR是整个记录(行)号和FNR是当前输入的记录数。 NR==FNR意味着第一个块只能在第一个输入上运行(在这种情况下,它是python脚本的输出)。输出被添加到缓冲区anext表示awk跳过其余的命令并转到下一行。

1是一种速记,它会导致打印文件中的所有行。当找到包含“级别:”的行时,还会打印缓冲区a的每一行。

您可以使用与上述相同的技巧将输出写入临时文件,然后覆盖原始文件。

+0

谢谢@Tom法语。用第一种方法,我得到错误:没有输入文件。 – as3rdaccount 2014-08-30 13:21:40

+0

我不知道你为什么得到这个错误。无论如何,使用'cat'的方法会在第一行**之前将行添加到文件的开头。第二种方法应该做你想做的。你试过了吗? – 2014-08-30 14:19:14

0

这应该做到这一点:

python test.py | 
awk ' 
    NR==FNR { a[NR] = $0; next } 
    { print (FNR==1 ? a[1] RS : "") $0 } 
    END { for (i=2;i in a;i++) print a[i] > ARGV[1] } 
' test.txt - 

上面读取的第一个文件到一个数组,然后关闭该开口从管来STDIN流之前文件,以便从此它可以安全地覆盖所述第一文件它的数组中的原始内容以您喜欢的任何顺序与来自管道的输入合并。

awk '...' file > file不同的是,这是完全安全的,因为它是awk而不是shell决定何时覆盖文件,只有当原始文件很大时才会出现内存使用和速度问题。

相关问题