bash 将历史文件中的哈希标签时间戳转换为所需的字符串

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10665396/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 02:19:32  来源:igfitidea点击:

converting the hash tag timestamps in history file to desired string

bashunixsshhistorytime-format

提问by user1356163

when i store the output of history command via ssh in a file i get something like this

当我通过 ssh 将历史命令的输出存储在一个文件中时,我得到了这样的东西

ssh -i private_key user@ip 'export HISTFILE=~/.bash_history; export HISTTIMEFORMAT="%D-%T "; set -o history; history' > myfile.txt


OUTPUT

输出

#1337431451
command

as far as ive learnt this hash string represents a timestamp. how do i change this to a string of my desired format

据我所知,这个哈希字符串代表一个时间戳。我如何将其更改为所需格式的字符串

P.S- using history in ssh is not outputting with timestamps. Tried almost everything. So i guess the next best thing to do would be to convert these # timestamps to a readable date time format myself. How do i go about it?

PS- 在 ssh 中使用历史记录不输出时间戳。几乎所有的东西都试过了。所以我想下一个最好的办法是自己将这些 # 时间戳转换为可读的日期时间格式。我该怎么做?

采纳答案by nosid

Interesting question: I have tried it but found no simple and clean solution to access the history in a non-interactive shell. However, the format of the history file is simple, and you can write a script to parse it. The following python script might be interesting. Invoke it with ssh -i private_key user@ip 'path/to/script.py .bash_history':

有趣的问题:我已经尝试过了,但没有找到在非交互式 shell 中访问历史记录的简单而干净的解决方案。但是,历史文件的格式很简单,你可以写一个脚本来解析它。以下 python 脚本可能很有趣。调用它ssh -i private_key user@ip 'path/to/script.py .bash_history'

#! /usr/bin/env python3

import re
import sys
import time

if __name__ == '__main__':
    pattern = re.compile(br'^#(\d+)$')
    out = sys.stdout.buffer
    for pathname in sys.argv[1:]:
        with open(pathname, 'rb') as f:
            for line in f:
                timestamp = 0
                while line.startswith(b'#'):
                    match = pattern.match(line)
                    if match: timestamp, = map(int, match.groups())
                    line = next(f)
                out.write(time.strftime('%F %T ', time.localtime(timestamp)).encode('ascii'))
                out.write(line)

回答by tmf glzkv

you can combine rows with paste command:

您可以将行与粘贴命令组合:

paste -sd '#\n' .bash_history

and convert date with strftime in awk:

并在 awk 中使用 strftime 转换日期:

echo 1461136015 | awk '{print strftime("%d/%m/%y %T",)}'

as a result bash history with timestamp can be parsed by the next command:

因此,可以通过下一个命令解析带有时间戳的 bash 历史记录:

paste -sd '#\n' .bash_history | awk -F"#" '{d= ; ="";print NR" "strftime("%d/%m/%y %T",d)" "
#1461137765
echo lala
#1461137767
echo bebe
}'

which converts:

它转换:

1 20/04/16 10:36:05   echo lala
2 20/04/16 10:36:07   echo bebe

to

#!/bin/bash

paste -sd '#\n'  | awk -F"#" '{d= ; ="";print NR" "strftime("%d/%m/%y %T",d)" "
fhistory .bash_history
}'

also you can create script like /usr/local/bin/fhistorywith content:

您也可以使用内容创建像/usr/local/bin/fhistory这样的脚本:

awk -F\# '/^#1[0-9]{9}$/ { if(cmd) printf "%5d  %s  %s\n",n,ts,cmd;
  ts=strftime("%F %T",); cmd=""; n++ }
  !/^#1[0-9]{9}$/ { if(cmd)cmd=cmd " " 
awk -F\# '/^#1[0-9]{9}$/ { if(cmd) printf "%s  %s\n",ts,cmd;
  ts=strftime("%F %T",); cmd="" }
  !/^#1[0-9]{9}$/ { if(cmd)cmd=cmd "\n" 
gawk -F\# -v histtimeformat="$HISTTIMEFORMAT" '
    /^#1[0-9]{9}$/ { i= FS NR; cmd[i]="" }
    !/^#1[0-9]{9}$/ { if(cmd[i]) cmd[i]=cmd[i] "\n" ##代码##; else cmd[i]=##代码## }
    END { PROCINFO["sorted_in"] = "@ind_str_asc"
       for (i in cmd) { split(i,arr)
       print strftime(histtimeformat,arr[1]) cmd[i]
    }
}'
; else cmd=##代码## }' .bash_history
; else cmd=##代码## }' .bash_history

and quickly parse bash history file with next command:

并使用下一个命令快速解析 bash 历史文件:

##代码##

回答by xebeche

Using just Awk and in a slightly more accurate way:

仅使用 awk 并以更准确的方式使用:

##代码##

This parses only lines starting with something that looks like a timestamp (/^#1[0-9]{9}$/), compiles all subsequent lines up until the next timestamp, combines multi-line commands with " "(1 space) and prints the commands in a format similar to historyincluding a numbering.

这仅解析以时间戳 ( /^#1[0-9]{9}$/)开头的行,编译所有后续行直到下一个时间戳,将多行命令与" "(1 个空格)组合在一起,并以类似于history包含编号的格式打印命令。

Note that the numbering does not (necessarily) match if there are multi-line commands.

请注意,如果有多行命令,编号不会(必然)匹配。

Without the numbering and breaking up multi-line commands with a newline:

没有编号和用换行符分解多行命令:

##代码##

Finally, a quick and dirty solution using GNU Awk (gawk) to also sort the list:

最后,使用 GNU Awk (gawk) 对列表进行排序的快速而肮脏的解决方案:

##代码##