AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / unix / 问题 / 469483
Accepted
Tran Triet
Tran Triet
Asked: 2018-09-17 20:57:36 +0800 CST2018-09-17 20:57:36 +0800 CST 2018-09-17 20:57:36 +0800 CST

Diff 输出“二进制文件 <file1> <file2> 不同”,但不是通常的详细输出

  • 772

我想使用命令比较两个文件 - “orienv”和“currenv” diff。

我创建这两个文件的方式如下:

  1. 创建“currenv”文件

    $cat /proc/1/environ >> currenv
    $cat /pcoc/279/environ >> currenv
    $cat /proc/295/environ >> currenv
    //295 is the pid of the current console
    
  2. 创建 orienv 文件

    $printenv > orienv
    

然后我打电话diff如下

diff -u orienv currenv

并得到以下输出

二进制文件 orienv 和 currenv 不同

我期待一个diff带有标志的正常输出-u(例如,它显示了hunks差异的输出,指示哪个文件具有另一个文件没有的信息。

什么地方出了错?

diff cat
  • 3 3 个回答
  • 7086 Views

3 个回答

  • Voted
  1. Gilles 'SO- stop being evil'
    2019-10-16T12:34:25+08:002019-10-16T12:34:25+08:00

    环境变量的值可以包含换行符。在中,变量由空字节分隔,空字节不能出现在环境变量的值或名称中。(这并非巧合的是,环境在内存中的表示方式。)当 diff 看到空字节时,它决定文件是二进制文件(根据定义这是真的:文本文件不包含空字节)并放弃显示差异,因为对于大多数二进制格式,打印出来的差异是没有用的。/proc/PID/environ

    您可以使用 告诉 diff 继续并将文件视为文本diff --text,但如果您在两个文件之间执行此操作,这可能会给您一个仅包含一两个大更改行的显示,因为实际上环境不会包含许多换行符。Diff 仅适用于用换行符分隔的行。如果您在 的内容和输出之间执行此操作,则表示一切都已更改,因为使用换行符作为分隔符。/proc/PID/environ/proc/PID/environprintenvprintenv

    要获得有用的输出,请将空字节转换为换行符。这样,每个环境变量都将从行首开始。

    diff -u orienv --label=currenv <(tr '\0' '\n' <currenv)
    

    为了获得有用且明确的输出,还将换行符转换为空字节,以便每个环境变量都在自己的单行上。然后,如果 diff 输出中有一个空字节,则表明原始文件在此位置包含换行符。

    diff -u --text --label=currenv <(tr '\0\n' '\n\0' <currenv1) --label=currenv <(tr '\0\n' '\n\0' <currenv2)
    
    • 2
  2. Best Answer
    Ipor Sircer
    2018-09-17T21:00:48+08:002018-09-17T21:00:48+08:00

    /proc/*/environ 不是文本文件。使用字符串:

    strings /proc/{1,279,295}/environ >> currenv
    env > orienv
    diff -u orienv currenv
    
    • 1
  3. 林果皞
    2019-12-18T06:17:12+08:002019-12-18T06:17:12+08:00

    问题是因为/proc/<pid>/environ包含空字节。您可以查看以文本表示的不可打印字节cat -v,例如,您可以在下面的输出中看到^@表示空字节:

    $ cat -v /proc/20148/environ 
    CLUTTER_IM_MODULE=xim^@COLORFGBG=15;0^@COLORTERM=truecolor^@ ...cont.
    

    尽管如此,在打印环境变量时需要考虑三个常见问题:

    1. ANSI 颜色转义码值将在终端上打印为“颜色”而不是文字,例如export p_red=$(tput setaf 1). 这会导致您的 diff 输出不需要的颜色,并且还缺少颜色代码值。diff --color=always由于颜色中断,也不会按预期工作。
    2. 函数定义通常包含多行。并且变量值也可能包含多行。例如:

      $ cat /etc/environment love=" 1st line 2nd line"

    3. sort没有first 的Diff会得到令人困惑的结果。

    您可以通过以下方式解决所有这些问题:

    $ sudo cat /proc/1/environ | tr '\n\0' ' \n' | cat -v > currenv
    $ sudo cat /proc/279/environ | tr '\n\0' ' \n' | cat -v >> currenv
    $ sudo cat /proc/295/environ | tr '\n\0' ' \n' | cat -v >> currenv
    $ sort -u currenv -o currenv
    $ printenv -0 | tr '\n\0' ' \n' | cat -v | sort -u > orienv
    $ diff --unified="$(cat currenv orienv | wc -l)" orienv currenv --color=always
    

    输出将是这样的:

    ...
     LOGNAME=xiaobai
     love= 1st line 2nd line
    ..
     PKG_CONFIG_PATH=:/usr/lib/pkgconfig:/usr/local/lib/pkgconfig
     p_lblue=^[[38;5;50m
     p_lgreen=^[[38;5;118m
     p_lred=^[[38;5;196m
     p_orig=^[(B^[[m
     p_red=^[[31m
     PROFILEHOME=
    ...
     QT_IM_MODULE=ibus
    +recovery=
    +rootmnt=/root
     S_COLORS=auto
    

    说明:

    1. tr '\n\0' ' \n'表示 的缩写形式tr '\n' ' ' | tr '\0' '\n'。我们先将换行符(即多行值)替换\n为空白' ',然后将空字节替换\0为换行符'\n'。我们不必担心多行可以是值或空字节的歧义,因为我们首先用空格替换多行值。
    2. printenv可以-0选择以NUL 结束每个输出行,而不是 newline。的输出printenv -0将与/proc/<pid>/environ. 所以我们可以做同样的事情tr '\n\0' ' \n'。
    3. sort -u进行排序,并删除重复的行以避免>> currenv继续附加相同的变量并且很难看到差异。
    4. 我们将统一值设置为 valuecat currenv orienv | wc -l以查看所有可能的统一值。diff工具实际上调用strtoumax()以转换该值,因此如果您传递负值,您将获得垃圾值。
    5. cat -v将颜色代码转换为可打印文本。我们无需担心cat -v需要单独的空字节和颜色代码,因为我们已经tr '\n\0' ' \n'首先替换了所有空字节。
    6. 最后,diff --color=always使用色块(绿色/红色/白色)打印差异。我们不必担心颜色代码会中断差异颜色,因为cat -v已经转换了颜色代码。
    • 0

相关问题

  • 确定两个 iso 图像是否相等

  • 串行设备输出在 gnu 屏幕中看起来不错,但使用 cat 时出现乱码

  • cat heredocument 复制了除函数调用之外的所有内容

  • git:仅在 GUI 中使用视觉差异(融合)

  • 这个命令是如何工作的?mkfifo /tmp/f; 猫/tmp/f | /bin/sh -i 2>&1 | 数控 -l 1234 > /tmp/f

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    如何将 GPG 私钥和公钥导出到文件

    • 4 个回答
  • Marko Smith

    ssh 无法协商:“找不到匹配的密码”,正在拒绝 cbc

    • 4 个回答
  • Marko Smith

    我们如何运行存储在变量中的命令?

    • 5 个回答
  • Marko Smith

    如何配置 systemd-resolved 和 systemd-networkd 以使用本地 DNS 服务器来解析本地域和远程 DNS 服务器来解析远程域?

    • 3 个回答
  • Marko Smith

    如何卸载内核模块“nvidia-drm”?

    • 13 个回答
  • Marko Smith

    dist-upgrade 后 Kali Linux 中的 apt-get update 错误 [重复]

    • 2 个回答
  • Marko Smith

    如何从 systemctl 服务日志中查看最新的 x 行

    • 5 个回答
  • Marko Smith

    Nano - 跳转到文件末尾

    • 8 个回答
  • Marko Smith

    grub 错误:你需要先加载内核

    • 4 个回答
  • Marko Smith

    如何下载软件包而不是使用 apt-get 命令安装它?

    • 7 个回答
  • Martin Hope
    rocky 如何将 GPG 私钥和公钥导出到文件 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Wong Jia Hau ssh-add 返回:“连接代理时出错:没有这样的文件或目录” 2018-08-24 23:28:13 +0800 CST
  • Martin Hope
    Evan Carroll systemctl 状态显示:“状态:降级” 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim 我们如何运行存储在变量中的命令? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S 为什么 /dev/null 是一个文件?为什么它的功能不作为一个简单的程序来实现? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 如何从 systemctl 服务日志中查看最新的 x 行 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - 跳转到文件末尾 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla 为什么真假这么大? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis 在一个巨大的(70GB)、一行、文本文件中替换字符串 2017-12-30 06:58:33 +0800 CST
  • Martin Hope
    Bagas Sanjaya 为什么 Linux 使用 LF 作为换行符? 2017-12-20 05:48:21 +0800 CST

热门标签

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve