追加コメント

追加コメント

script -c私は進捗状況を監視し、結果を電子メールで送信できるようにコマンドを実行し、出力をログファイルに記録して一石二鳥を試みるbashスクリプトを持っています。

最終ログファイルは、すべての進捗状況の出力が記録されるターミナルセッションに表示されるすべてのエントリのタイプスクリプトであるため、かなり長いです。ただし、read dataを使用すると、cat端末に最終出力のみが表示されます。

たとえば、 script -c 'rsync -ah --info=progress2 folder1 folder2' logfile.log

次のコマンドを使用してファイルを開きますnano

> # nano logfile.log
Script started on 2021-07-20 14:22:40+0800
^M         36.84M   0%   34.31GB/s    0:00:00 (xfr#1, to-chk=606/673)^M        808.26M   7%  752.75GB/s    0:00:00 (xfr#31, to-chk=603/673)^M        860.63M   7%  801.52GB/s    0:00:00 (xfr#34, to-chk=592/673)$

Script done on 2021-07-20 14:22:40+0800

一方、cat

> # cat logfile.log                                                                                                                                                                                              
Script started on 2021-07-20 14:22:40+0800
         11.48G 100% 10693.06GB/s    0:00:00 (xfr#616, to-chk=0/673)

Script done on 2021-07-20 14:22:40+0800

ただし、cat出力がファイルに書き込まれる場合:

> # cat logfile.log > temp.log

結果には、temp.log生データ全体が含まれます。


  1. 違いがあるのはなぜですか?

  2. catディスプレイの生出力ではなく、ディスプレイから得られたものと同じ出力を電子メールで送信したいと思いますnano。ただし、cat生データは常にファイル、他のコマンドなどに出力されます。

以下のコマンドは、電子メールで生データを送信します。

> # echo -e "Subject : report" "\n\n\n `cat logfile.log`" | sendmail [email protected]
  1. TypeScriptファイルからすべての生データを消去する方法はありますか?オンラインまたはマニュアルで何も見つかりませんでした。

追加コメント

アドバイスと説明ありがとうございます。実際にコメントで提案されているようにとを使用して出力を整理することができました
rsynctrsed

ただし、プログラムなしでコマンドを実行したり、-v他のプログラム(たとえば)を実行したりすると、resticログに多数の削除シーケンスが表示されます。

^[[2K[13:34] 487210 files 165.864 GiB, total 503917 files 230.290 GiB, 0 errors

^[[2K[13:34] 487218 files 165.972 GiB, total 503960 files 230.477 GiB, 0 errors

^[[2KFiles:         176 new,     3 changed, 633544 unmodified

^[[2K

^[[2KDirs:          260 new,   140 changed, 106144 unmodified

^[[2K

^[[2KAdded to the repo: 363.231 MiB

^[[2K

^[[2K

^[[2K

^[[2Kprocessed 633723 files, 535.105 GiB in 14:34

^[[2K

^[[2Ksnapshot 9394ca81 saved

^[[2K

^[[2K

^[[1A
Script done on 2021-07-20 00:06:12+0800

のあるアイテムを削除できますsed

cat端末の最後の出力をファイルに直接書き込むかパイプする方法がある場合は、よりクリーンで一般的な解決策になりますかsponge

ベストアンサー1

さて、ここにこのクリーンアップを試みる(比較的)単純なPythonスクリプトがあります。私はそれを呼ぶclean-typescript.py。確かに改善することができ、バグがあるかもしれませんが、これは私が短い時間内に思い出すことができるものです。

#!/usr/bin/env python3
# Takes raw terminal output of a program containing control sequences that
# overwrite parts of the output, and attempts to transform it to just the end
# result, writing its output on stdout.
#
# Assumptions/limitations:
#  * Assumes Unix line endings.
#  * Assumes input text is left-to-right, in system character encoding.
#  * Does not attempt to deal with most of the complexities of Unicode.
#  * Does not attempt to interpret every ANSI escape sequence; just the common
#    ones that affect cursor position.
#  * Ignores ANSI SGR (bold/color/etc.) sequences.
#  * Assumes 8-column tab stops.
#  * Assumes the terminal displays an unlimited number of lines.
#  * Ignores absolute positioning sequences (except CHA): this is not for
#    ncurses output and such.
#  * Will not allow the cursor to go up beyond the first line in the file.
#
# Usage: clean-typescript.py FILE COLS
# FILE is the name of the file to read; if omitted or "-", read stdin.
# COLS is how many columns wide the terminal is; if omitted, set to 80.

import sys
from array import array
from enum import Enum

if len(sys.argv) >= 2 and sys.argv[1] != "-":
    f = open(sys.argv[1], "r")
else:
    f = sys.stdin

if len(sys.argv) >= 3:
    cols = int(sys.argv[2])
else:
    cols = 80

lines = [array("u", (" ",)*cols)]
curline = curcol = 0
eol = False

class Dir (Enum):
    UP = 0
    DOWN = 1
    RIGHT = 2
    LEFT = 3

def move_cursor (dir: Dir, count: int):
    global curline, curcol, eol
    if dir == Dir.UP:
        pos = curline - count
        curline = pos if pos >= 0 else 0
    elif dir == Dir.DOWN:
        pos = curline + count
        curline = pos if pos < len(lines) else len(lines) - 1
    elif dir == Dir.RIGHT:
        pos = curcol + count
        curcol = pos if pos < cols else cols - 1
    elif dir == Dir.LEFT:
        eol = False
        pos = curcol - count
        curcol = pos if pos >= 0 else 0

def skip_osc ():
    c = f.read(1)
    while True:
        if c == "\x07":
            return f.read(1)
        if c == "\x1b":
            if f.read(1) == "\\":
                return f.read(1)
        c = f.read(1)

def interpret_seq ():
    c = f.read(1)
    if c == "]": # OSC
        return skip_osc()
    if c != "[": # CSI
        # Other Fe seqs. not supported
        return f.read(1)

    parms = []
    c = f.read(1)
    while True:
        p = ""
        while c >= "0" and c <= "9":
            p += c
            c = f.read(1)
        if p:
            parms.append(int(p))

        if c != ";": break
        c = f.read(1)

    if c == "A":   # CUU
        move_cursor(Dir.UP, parms[0] if len(parms) > 0 else 1)
    elif c == "B": # CUD
        move_cursor(Dir.DOWN, parms[0] if len(parms) > 0 else 1)
    elif c == "C": # CUF
        move_cursor(Dir.RIGHT, parms[0] if len(parms) > 0 else 1)
    elif c == "D": # CUB
        move_cursor(Dir.LEFT, parms[0] if len(parms) > 0 else 1)
    elif c == "E": # CNL
        move_cursor(Dir.LEFT, cols)
        move_cursor(Dir.DOWN, parms[0] if len(parms) > 0 else 1)
    elif c == "F": # CPL
        move_cursor(Dir.LEFT, cols)
        move_cursor(Dir.UP, parms[0] if len(parms) > 0 else 1)
    elif c == "G": # CHA
        move_cursor(Dir.LEFT, cols)
        move_cursor(Dir.RIGHT, parms[0] - 1 if len(parms) > 0 else 0)
    # CUP and ED not implemented
    elif c == "K": # EL
        if (len(parms) == 0 or parms[0] == 0) and not eol:
            for i in range(curcol, cols):
                lines[curline][i] = " "
        elif parms[0] == 1:
            for i in range(0, curcol):
                lines[curline][i] = " "
            if eol:
                append_line()
                move_cursor(Dir.LEFT, cols)
                move_cursor(Dir.DOWN, 1)
        elif parms[0] == 2:
            for i in range(0, cols):
                lines[curline][i] = " "
            if eol:
                append_line()
                move_cursor(Dir.LEFT, cols)
                move_cursor(Dir.DOWN, 1)
    # ED, SU, SD, and HVP also not implemented

    c = f.read(1)
    return c

def append_line ():
    lines.append(array("u", (" ",)*cols))

c = f.read(1)
while c:
    if c == "\x08":   # BS
        if eol:
            eol = False
        else:
            move_cursor(Dir.LEFT, 1)
    elif c == "\x09": # HT
        curcol = (curcol + 8)//8*8
        if curcol >= cols: curcol = cols - 1
    elif c == "\x0a": # LF (implies CR in Unix)
        eol = False
        if curline == len(lines) - 1: append_line()
        move_cursor(Dir.LEFT, cols)
        move_cursor(Dir.DOWN, 1)
    elif c == "\x0b" or c == "\x0c": # VT/FF: just go down one line
        if curline == len(lines) - 1: append_line()
        move_cursor(Dir.DOWN, 1)
    elif c == "\x0d": # CR (stays on same line)
        eol = False
        move_cursor(Dir.LEFT, cols)
    elif c == "\x1b": # Escape seq.
        c = interpret_seq()
        continue
    elif (c >= "\x20" and c <= "\x7e") or c >= "\xa1":
        if not eol: lines[curline][curcol] = c
        if curcol == cols - 1:
            if eol:
                if curline == len(lines) - 1: append_line()
                move_cursor(Dir.LEFT, cols)
                move_cursor(Dir.DOWN, 1)
                lines[curline][curcol] = c
                move_cursor(Dir.RIGHT, 1)
            else:
                eol = True
        else:
            move_cursor(Dir.RIGHT, 1)

    c = f.read(1)

# Final result
print(*("".join(line).rstrip() for line in lines), sep="\n", end="")

おすすめ記事