如何从 DNF 和 YUM 命令中删除换行?

如何从 DNF 和 YUM 命令中删除换行?

当在基于 rpm 的 Linux 发行版(RHEL/Red Hat、Fedora、CentOS 等)上使用时dnfyum该实用程序将自动换行以使其更适合用户阅读。这是有问题的,因为它使得通过管道处理数据变得非常烦人。

例如:

$ dnf search jenkins-ssh-credentials-plugin-javadoc
Last metadata expiration check: 6 days, 15:30:08 ago on Thu Sep  1 21:09:10 2016.
============= N/S Matched: jenkins-ssh-credentials-plugin-javadoc =============
jenkins-ssh-credentials-plugin-javadoc.noarch : Javadoc for jenkins-ssh-credentials-plugin
$ dnf search jenkins-ssh-credentials-plugin-javadoc | grep ssh
====== N/S Matched: jenkins-ssh-credentials-plugin-javadoc =======
jenkins-ssh-credentials-plugin-javadoc.noarch : Javadoc for
                                              : jenkins-ssh-credentials-plugin

您可以看到,一旦 DNF 的输出通过,grep它就会决定以与通常向用户显示时完全不同的方式包装数据。

已针对此行为提出了多个问题(#584525,#986740)并且问题始终被关闭,CLOSED NOTABUG因为“Yum 是一个基于文本的交互式用户界面,不适合也不适合管道。”。红帽开发人员的解决方案是“使用不同的工具来完成这项工作”。

必须这样做似乎是不合理的,特别是当提供的方法(repoquery例如安装)甚至不存在dnf实用程序中,需要安装更多的软件包才能解析该数据的输出。

理想情况下,用户能够在管道中使用数据。取而代之的是,如果有一个简单的单行代码可以用来使数据可用,那就太好了。

答案1

有一个很棒的“示例”命令/咒语列表,sed这些命令/咒语已经通过名称sed1line.txthttp://sed.sourceforge.net/sed1line.txt)。在这个文件中有一个很好的例子,在这种情况下很有帮助:

# if a line begins with an equal sign, append it to the previous line
# and replace the "=" with a single space
sed -e :a -e '$!N;s/\n=/ /;ta' -e 'P;D'

dnf在/输出的情况下,yum我们知道换行将以一个或多个空格实例开始,后跟一个冒号 (:),然后是更多空格。利用这些知识,我们可以修改 sed 示例来解释这一点并加入以下行:

sed -r -e :a -e '$!N;s/\n[[:space:]]+://;ta' -e 'P;D'

在这种情况下,我们需要做出决定,因为 是+“扩展”正则表达式集的一部分,我们需要添加-r来使用该+符号,或者回退到*在它的位置使用(这将匹配零个或多个空白)。两者都可以,上面的例子是为了迂腐而正确的。

结果如下:

$ dnf search jenkins-ssh-credentials-plugin-javadoc | sed -r -e :a -e '$!N;s/\n[[:space:]]+://;ta' -e 'P;D'  | grep ssh
============= N/S Matched: jenkins-ssh-credentials-plugin-javadoc ==============
jenkins-ssh-credentials-plugin-javadoc.noarch : Javadoc for jenkins-ssh-credentials-plugin

如您所见,现在grep可以按预期工作。此外,这还允许您对输出进行更有创意的格式化,从而更轻松地扫描包列表:

$ dnf search ssh | sed -r -e :a -e '$!N;s/\n[[:space:]]+://;ta' -e 'P;D' | sort  | awk -F: '!($1~/^====/) {printf "%-40s : %s\n", $1, substr($0, index($0, $2))}'
ansible.noarch                           :  SSH-based configuration management, deployment, and task execution system
apache-sshd-javadoc.noarch               :  API documentation for apache-sshd
apache-sshd.noarch                       :  Apache SSHD
autossh.x86_64                           :  Utility to autorestart SSH tunnels
bareftp.x86_64                           :  File transfer client supporting the FTP, FTP over SSL/TLS (FTPS) and SSH
belier.noarch                            :  Generates scripts allowing you to chain many ssh connections
btrfs-sxbackup.noarch                    :  Incremental btrfs snapshot backups with push/pull support via SSH
...
trilead-ssh2.noarch                      :  SSH-2 protocol implementation in pure Java
WebShell.noarch                          :  SSL server for web-based SSH access from browsers and mobile devices
x11-ssh-askpass.x86_64                   :  A passphrase dialog for X and not only for OpenSSH

答案2

yumdnf编写进度消息,使用回车符重划一行。这些消息不是包裹grep不是为此设计的,假设行没有嵌入控制字符。grep确实对终端做了一些假设,但那是不同的故事

我使用 sed 脚本将过度打印的行过滤为“最终”行(删除所有过度打印的部分)。在示例中script2log.sed,

# $Id: script2log.sed,v 1.3 2015/02/04 23:50:12 tom Exp $
#
# Trim ordinary ANSI sequences, then OSC sequences, then backspace
# sequences, then trailing CR's and finally overstruck sections of
# lines.
#
# There are still several interesting cases which cannot be handled
# with a script of this sort.  For example:
#       CSI K (clear line)
#       cursor movement within the line
s/␛[[][<=>?]\{0,1\}[;0-9]*[@-~]//g
s/␛[]][^␛]*␇//g
s/␛[]][^␛]*␛\\//g
:loop
s/[^␈]␈\(.\)/\1/g
t loop
s/␍␍*$//g
s/^.*␍//g
s/␛[^[]//g

这是通过这两个命令完成的,它首先删除一行中任意数量的尾随回车符,然后删除该行中包括回车符的任何部分。剩下的只是要写入的行的最后一个副本(您想要的):

s/␍␍*$//g
s/^.*␍//g

(是的,这些是脚本中的回车符)。

yum当我捕获(或)的输出时dnf,我不会尝试通过管道传输到grep(这肯定会产生不良结果)。相反,我用来script捕获输出,并使用后处理sed,例如,

script -c "yum upgrade"
sed -f script2log.sed typescript >upgrade.log

相关内容