如何通过 `awk` 或 `sed` 在 Ubuntu 终端变量的末尾添加一些字符?

Posted

技术标签:

【中文标题】如何通过 `awk` 或 `sed` 在 Ubuntu 终端变量的末尾添加一些字符?【英文标题】:How do I add some characters at the end of an Ubuntu terminal variable via `awk` or `sed`? 【发布时间】:2021-06-25 21:37:03 【问题描述】:

上下文

我目前正在尝试在我的 Windows 10 Pro 操作系统中设置适用于 Linux 的 Windows 子系统 2。从 Microsoft 商店下载 Ubuntu 20.04 LTS、安装它并创建我的用户配置文件后,我开始想知道如何运行和使用所有具有图形界面的 Ubuntu 程序。然后我发现了Xming,它允许我通过 IP 在我的 Windows 操作系统和 Ubuntu 内核之间建立连接:一切正常,除了因为无法为 WSL 虚拟以太网卡设置静态 IP ,每次我重新启动我的电脑时,我都必须检查并更改我要连接的地址。我目前正在通过每次编辑我的.bashrc 文件来执行此操作,并添加如下行

export DISPLAY=172.29.112.1:0.0

它对应于我在 WSL Web 配置的 IPv4 子部分中列出的 IP。我是通过运行得到的

ipconfig

在 PowerShell/Windows 终端内。我添加到 IP 的两个零是 Xming 请求的端口,(也间接地,我的问题的原因)。

我的想法是尝试自动化所有这些过程,这样每次我启动我的电脑时,我只需要启动 Xming 和 Ubuntu。

问题描述

问题是我对终端语法的了解几乎为零,所以我设法提出了一个部分解决方案:我设法自动加载正确的 IP,但如果不删除部分 IP,我就无法附加端口本身。到目前为止,这是我想出的:

export DISPLAY=$(/mnt/c/Windows/System32/ipconfig.exe | grep IPv4 | cut -d: -f2 | awk 'print $1' | awk 'ENDprint')

添加到我的.bashrc 的这一行允许我获得正确的 IPv4,它恰好总是位于列表末尾的那个(因此第二个awk 调用)。它调用在 Windows 中使用的相同的ipconfig,以便我可以获得所需的地址。 我研究了一下这种语法是如何工作的,并为下一个问题找到了一些有趣的解决方案,即在上面的查询末尾附加 ':0.0'。例如,一个是this。不幸的是,即使使用普通字符串复制该解决方案也可以正常工作,但似乎我的 IP 地址被存储为不同类型的变量,或者至少它的行为不同:尝试应用相同的概念会使我的 IP 的初始部分被覆盖。

我想要什么

一个(可能)像我做的那样的单行公式,但它也在末尾合并了端口,而不会覆盖任何 IP 的数字。在任何情况下,在.bashrc 中分配的DISPLAY 变量必须与我在部分实现中拥有的当前变量的类型相同,因为我需要Xming 或任何其他程序读取它。我还希望对解决方案以及我描述的覆盖现象的原因进行一些解释。

到目前为止我所做的尝试

我花了一个下午的时间来解决这个问题,从学习一点 Ubuntu 终端的语法开始,以及尝试查找 sedawk 的示例以及其他功能。为了适应端口,我还尝试了许多稍微更改的查询版本,但所有这些尝试仅产生语法错误或上述相同的覆盖效果。

我为什么要问这个

鉴于我预计这可能需要我一段时间才能解决,并且我相信对于任何具有该领域经验的人来说这根​​本不应该是耗时的,我希望得到一些帮助。

谢谢!

更新

经过多次尝试,事实证明 WSL IP 子类别确实可以列在与上一个不同的位置。我原以为这些条目会按照字母顺序排列,但现在很明显这只是一个巧合。 因此,如果我有这样的事情:

我现在需要实际grep ipconfig 输出的这个精确部分,而不是像我一直在做的那样盲目地选择列表的最后一个。我试图围绕您的解决方案展开思考,并且通过一些进一步的研究,我设法找到了一种使其工作的方法,而不管定位如何:

export DISPLAY=$(/mnt/c/Windows/System32/ipconfig.exe | awk '/WSL/getline; getline; getline; getline; print' | grep IPv4 | cut -d: -f2 | tail -n1 | sed 's/\r//g' | awk 'END print($1":0.0");')

获得附加@Zilog80 公式。我的理解是getline 应该读取并忽略当前行并移至下一行,因此通过这样做 4 次,我可以将公式的其余部分应用于我最初感兴趣的行。肯定有更好的方法这样做,但我可以确认这是非常可靠的,即使不优雅。期待看到您对此更新的建议/改进。 ps 我删除了部分 IPv6,因为我不知道这是否是明智的信息;抱歉,如果不是这样。

【问题讨论】:

您能否创建一个 bash 脚本,在单独的变量中收集您需要的信息,然后将它们组合成一个变量?然后你只需要运行一个命令来运行脚本。 @wxz 这可能是一个想法,尽管有一个单行解决方案会更优雅。而且我认为“数据类型”也会有同样的问题。更新:我尝试了其中一个答案并且它有效,所以我想没有问题了。也感谢您的帮助! :) DISPLAY=:0.0 不工作吗? 据我记得,这是我尝试的第一件事,但没有成功编辑:无论如何,这个问题已经过去一个月了,所以我可能说错了。也许当我重新开始在 Windows 上工作时我会再试一次 @DiegoTorresMilano 我可以确认DISPLAY=:0.0 不起作用,至少对我而言。 【参考方案1】:

您遇到的问题是您正在启动 ipconfig.exe,这是一个用于 ip 适配器的 Windows 工具,它使用 Windows 行终止符 (CR+LF) 输出。这促使 AWK 将 CR 保留在输出中,因此 overwriting

为防止这种情况,请使用sed 实用程序过滤该死的 CR,该实用程序允许删除麻烦的 CR (\r):

export DISPLAY=$(/mnt/c/Windows/System32/ipconfig.exe | grep IPv4 | cut -d: -f2 | tail -n1 | sed 's/\r//g' | awk 'END print($1":0.0");')

正如@Ed Morton 所建议的,让您知道您的所有命令都可以仅使用AWK 来完成可能会很有用:

export DISPLAY=$(/mnt/c/Windows/System32/ipconfig.exe | awk -F\: '/IPv4/adr=$NFENDsub(/\r$/,"",adr); print adr":0:0"')

【讨论】:

谢谢!这完美无瑕!我永远不会弄清楚线路终结器的问题。我看到有很多方法可以做到这一点,我会尝试围绕所有这些不同的版本。另外,有没有人介意给我一些链接,让我真正掌握如何利用这些 bash 功能?再次感谢您! @Jetboy 在发布的任何答案中都有 very 小 bash(只有 $() 并且没有 bash 函数),几乎所有的工作都在完成通过强制性 POSIX 工具 grep、cut、sed 和 awk。在任何 Unix 机器上,您都可以键入 man grep 等来查看他们的手册页。这对于 grep、cut 和 sed 来说应该足够了,但对于 awk(一种用于操作文本的完整编程语言),您应该阅读 Arnold Robbins 的《Effective AWK Programming, 5th Edition》一书。 缺乏术语肯定是我的问题的一部分——我正在尝试在没有充分事先研究的情况下做一些事情。我这样做是因为这些天我在许多“领域”中遇到了许多不同的问题(为论文/考试工作),并且研究“应该如何完成”的所有内容将花费我太多时间。尽管如此,我发现这个特殊的灰色(黑色)区域我必须特别有趣——我想也很严肃。感谢您也更正我的词典 不用担心,有多年经验的人说 Linux 指的是 Unix,bash 指的是 shell,bash 指的是 Unix,bash 指的是 awk,指一些不存在的 sed/awk等等。这需要一点时间来适应,但是一旦您了解了不同之处,使用适合每个任务的工具就会变得更加简单! @EdMorton 更新了您的建议。我必须承认我总是很想杀死所有可能的 CR。【参考方案2】:

抱歉,我没有阅读所有部分,只阅读了您的问题描述和“我想要什么”。这应该可以帮助您:

export DISPLAY=$(/mnt/c/Windows/System32/ipconfig.exe | sed 's/\r$//' | awk '/IPv4/ip=$NFENDprint ip ":0:0"')
您的 windows 命令给出了 DOS 行结尾。我用sed 转换它们。 awk 将包含IPv4 的所有行的最后一个字段存储在变量ip 中,该变量最终被打印出来。 awk 可以连接字符串:print ip ":0:0"

P。 S.:不要忘记替换 .bashrc 中先前附加的行。

【讨论】:

谢谢,您的回答也很有帮助。最后我给@Zilog80打勾只是因为他早了半秒就回答了。如果可以的话,我会平分所有的积分和被“选中”的荣耀。再次感谢您!【参考方案3】:

这是一个较短的单行代码,利用@Zilog80 关于回车的观点:

export DISPLAY=$(/mnt/c/Windows/System32/ipconfig.exe| awk '/IPv4/ addr=$NF END printf "%.*s:0.0", length(addr)-1, addr')

这会搜索其中嵌入了“IPv4”的行,并捕获该行中最后一个以空格分隔的项目。最后,它打印出来,将字符串限制为第一个长度为 1 的字符(删除回车)。

【讨论】:

以上是关于如何通过 `awk` 或 `sed` 在 Ubuntu 终端变量的末尾添加一些字符?的主要内容,如果未能解决你的问题,请参考以下文章

shell中 sed或awk 通过分隔符删除相应字段

使用 sed 或 awk 预处理 C/C++ 代码时如何定位可靠的函数?

如何在 SED 或 AWK 的行中添加双引号?

如何使用 sed 或 awk 正确查找和替换多行文本?

如何使用 sed、awk 或 gawk 仅打印匹配的内容?

如何在两个模式之间打印线,包括或不包括(在 sed、AWK 或 Perl 中)?