Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Linux 注销到文件时实时处理退格控制字符(^H)_Linux_Bash_Shell_Cat - Fatal编程技术网

Linux 注销到文件时实时处理退格控制字符(^H)

Linux 注销到文件时实时处理退格控制字符(^H),linux,bash,shell,cat,Linux,Bash,Shell,Cat,我正在编写一个脚本,在后台测试新的硬盘驱动器(这样我就可以关闭终端窗口)并记录输出。我的问题是让badblocks将标准输出打印到日志文件中,这样我就可以监控它的多日进度并创建格式正确的更新电子邮件 我已经能够使用以下内容将stdout打印到日志文件中:(标志为r/w,%monitor,verbose) sudo badblocks-b4096-wsv/dev/sdx2>&1 | tee sdx.log 通常,输出如下所示: 使用模式0xaa进行测试:完成2.23%,已过7:00。(0/0/0错

我正在编写一个脚本,在后台测试新的硬盘驱动器(这样我就可以关闭终端窗口)并记录输出。我的问题是让badblocks将标准输出打印到日志文件中,这样我就可以监控它的多日进度并创建格式正确的更新电子邮件

我已经能够使用以下内容将stdout打印到日志文件中:(标志为r/w,%monitor,verbose)

sudo badblocks-b4096-wsv/dev/sdx2>&1 | tee sdx.log

通常,输出如下所示:
使用模式0xaa进行测试:完成2.23%,已过7:00。(0/0/0错误)

不使用新行字符,^H control命令将备份光标,然后新的更新状态将覆盖以前的状态

不幸的是,控制字符未被处理,而是作为字符保存在文件中,产生上述输出,然后是43份
^H
、新更新的统计数据、43份
^H
,等等

由于输出至少每秒更新一次,因此生成的文件比需要的文件大得多,并且很难检索当前状态

在终端中工作时,解决方案
cat sdx.log&&echo”“
通过解析控制字符(然后插入回车符,使其不会立即被下一个终端行打印)打印预期/想要的结果,但是使用
cat sdx.log>some.file
cat sdx.log | mail
这两种方法仍然包含所有额外字符(尽管在电子邮件中它们被解释为空格)。这种解决方案(或类似于在访问时解码或删除控制字符的解决方案)仍然会产生一个巨大的、不必要的输出文件

我已经解决了以下类似的问题,但没有一个产生(至少我能弄明白)一种实时处理输出以更新文件的解决方案,它要求在任务完成写入后单独处理保存的日志文件,或者在过程完成之前不写入日志文件,这两种方法都无法实现监控进度的既定目标


谢谢!

您可以删除
^H

sudo badblocks -b 4096 -wsv /dev/sdx 2>&1 | tr -d '\b' | tee sdx.log

我在现实生活中遇到的主要问题是试图处理手册页。在过去,我总是使用一个简单的脚本,通过适当地剥离退格来进行后期处理。在80个字符的perl中,可能可以做这种事情,但这里有一种方法可以很好地处理退格和cr/nl。我没有测试过e从广义上讲,但对于简单的情况,它可以产生良好的输出。例如:

$ printf 'xxx\rabclx\bo\rhel\nworld\n' | ./a.out output
hello
world
$ cat output
hello
world
$ xxd output
00000000: 6865 6c6c 6f0a 776f 726c 640a            hello.world.
如果您的输出开始有很多csi序列,那么这种方法就不值得费心了。
cat
将为这些情况产生良好的人类可消费输出

#include <assert.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

FILE * xfopen(const char *path, const char *mode);
off_t xftello(FILE *stream, const char *name);
void xfseeko(FILE *stream, off_t offset, int whence, const char *name);

int
main(int argc, char **argv)
{
        const char *mode = "w";
        char *name = strchr(argv[0], '/');
        off_t last = 0, max = 0, curr = 0;
        name = name ? name + 1 : argv[0];
        if( argc > 1 && ! strcmp(argv[1], "-a")) {
                argv += 1;
                argc -= 1;
                mode = "a";
        }
        if( argc > 1 && ! strcmp(argv[1], "-h")) {
                printf("usage: %s [-a] [-h] file [ file ...]\n", name);
                return EXIT_SUCCESS;
        }
        if( argc < 2 ) {
                fprintf(stderr, "Missing output file.  -h for usage\n");
                return EXIT_FAILURE;
        }
        assert( argc > 1 );
        argc -= 1;
        argv += 1;

        FILE *ofp[argc];
        for( int i = 0; i < argc; i++ ) {
                ofp[i] = xfopen(argv[i], mode);
        }
        int c;
        while( ( c = fgetc(stdin) ) != EOF ) {
                fputc(c, stdout);
                for( int i = 0; i < argc; i++ ) {
                        if( c == '\b' ) {
                                xfseeko(ofp[i], -1, SEEK_CUR, argv[i]);
                        } else if( isprint(c) ) {
                                fputc(c, ofp[i]);
                        } else if( c == '\n' ) {
                                xfseeko(ofp[i], max, SEEK_SET, argv[i]);
                                fputc(c, ofp[i]);
                                last = curr + 1;
                        } else if( c == '\r' ) {
                                xfseeko(ofp[i], last, SEEK_SET, argv[i]);
                        }
                }
                curr = xftello(ofp[0], argv[0]);
                if( curr > max ) {
                        max = curr;
                }
        }
        return 0;
}

off_t
xftello(FILE *stream, const char *name)
{
        off_t r = ftello(stream);
        if( r == -1 ) {
                perror(name);
                exit(EXIT_FAILURE);
        }
        return r;
}

void
xfseeko(FILE *stream, off_t offset, int whence, const char *name)
{
        if( fseeko(stream, offset, whence) ) {
                perror(name);
                exit(EXIT_FAILURE);
        }
}

FILE *
xfopen(const char *path, const char *mode)
{
        FILE *fp = fopen(path, mode);
        if( fp == NULL ) {
                perror(path);
                exit(EXIT_FAILURE);
        }
        return fp;
}
#包括
#包括
#包括
#包括
#包括
文件*xfopen(常量字符*路径,常量字符*模式);
off_t xftello(文件*流,常量字符*名称);
void xfseko(文件*流、偏移量、整数、常量字符*名称);
int
主(内部argc,字符**argv)
{
常量字符*mode=“w”;
char*name=strchr(argv[0],'/');
关闭\u t last=0,max=0,curr=0;
name=name?name+1:argv[0];
如果(argc>1&&!strcmp(argv[1],“-a”)){
argv+=1;
argc-=1;
mode=“a”;
}
如果(argc>1&&!strcmp(argv[1],“-h”)){
printf(“用法:%s[-a][h]文件[文件…]\n”,名称);
返回退出成功;
}
如果(argc<2){
fprintf(stderr,“缺少用于使用的输出文件。-h”);
返回退出失败;
}
断言(argc>1);
argc-=1;
argv+=1;
文件*ofp[argc];
对于(int i=0;i最大值){
最大值=当前值;
}
}
返回0;
}
关
xftello(文件*流,常量字符*名称)
{
off_t r=ftello(溪流);
如果(r==-1){
佩罗尔(姓名);
退出(退出失败);
}
返回r;
}
无效的
xfseko(文件*流、偏移量、int whence、常量字符*名称)
{
if(fseeko(流、偏移、何处)){
佩罗尔(姓名);
退出(退出失败);
}
}
文件*
xfopen(常量字符*路径,常量字符*模式)
{
FILE*fp=fopen(路径、模式);
如果(fp==NULL){
佩罗尔(路径);
退出(退出失败);
}
返回fp;
}

我从来没有使用过
badblocks
,所以为了确保我理解正确:你是说它打印一行末尾没有换行符,然后多次打印退格符以删除内容并打印一个新版本的行,一次又一次,直到它完成为止,最后打印出来t换行?您希望任何给定点的
sdx.log
的内容成为该行的当前内容吗?是的,这是正确的(questi