awk 在匹配模式之前打印整行

Posted

技术标签:

【中文标题】awk 在匹配模式之前打印整行【英文标题】:awk print full line before the matched pattern 【发布时间】:2022-01-16 06:52:46 【问题描述】:

重新撰写的帖子

重要 *大家早上好,谢谢你的cmets和答案,我现在不在我的电脑里,所以我可能需要稍后尝试一些答案,我会将对我有用的答案标记为正确的解决方案。如果我在这篇文章中的措辞不是最好的,我深表歉意,我昨晚筋疲力尽,在发布这篇文章之前我什至没有检查我的措辞。 *

我会更好地澄清我的问题:

所以我有一个脚本,我们将其称为./run.sh,在该脚本内部我有一个变量,称为SCRIPT=DIR

这个变量运行一个命令 cd -- "$( dirname -- "$BASH_SOURCE[0]" )" &> /dev/null && pwd

所以完整的变量看起来像:

SCRIPT_DIR="$( cd -- "$( dirname -- "$BASH_SOURCE[0]" )" &> /dev/null && pwd )"

然后在该变量下面我有一个打印变量 SCRIPT_DIR 的回显 echo $SCRIPT_DIR 当我运行脚本./run.sh 时,我打印了以下字符串 /home/vMX-ENV/vMX-21.1R1/scripts/boot/

我的问题是,通过使用 awk 从给定字符串中删除文本,我想删除 scripts/boot/ 所以,我正在考虑匹配 scripts/ 之类的模式并打印 scripts/ 之前的每一行。通过仅将 scripts/ 与 awk 匹配,我希望能够得到如下结果: /home/vMX-ENV/vMX-21.1R1/

我找了很长时间,但找不到类似的东西并没有答案,我尝试了其他人在另一篇文章中给出的命令,该命令打印了匹配模式之前的内容,我试图修改该命令以适合我的脚本,但没有成功。希望这更好理解!

再次抱歉

---- 上一篇文章 ---- 请忽略 所以我知道有很多帖子试图解决这个问题;但是,我还没有成功地做到这一点!所以我有一个脚本,它告诉我我的 bash 脚本所在的目录,这是我从另一篇文章中获取的:

#SCRIPT_DIR="$( cd -- "$( dirname -- "$BASH_SOURCE[0]" )" &> /dev/null && pwd )"
/home/vMX-ENV/vMX-21.1R1/scripts/boot

我正在尝试从结果中删除 /scripts/boot 目录,因此它最终会是:

/home/vMX-ENV/vMX-21.1R1/

我正在尝试使用awk 作为我的解决方案,我知道还有其他命令,例如 grep 或 perl,但我宁愿使用 awk 只是为了保持一致。有谁知道我怎样才能做到这一点?我有过很多次不成功的尝试

有人在另一个帖子上建议使用

awk '/foo/if (a && a !~ /foo/) print a; print a=$0' file

但我无法让它工作。此外,我对 bash 没有太多经验,所以我想不出解决它的方法。有什么帮助吗?

【问题讨论】:

不确定我是否理解您发布的两行“脚本”...您是说SCRIPT_DIR 变量包含字符串/home/vMX-ENV/vMX-21.1R1/scripts/boot?还是字符串/home/vMX-ENV/vMX-21.1R1/scripts/boot 是脚本中的硬编码行(如果是这样,#SCRIPT_DIR= 行的意义是什么)?这与主题print full line before the matched pattern 有什么关系...什么“模式”和什么“全线”? 我无法想象你发布的那个 awk 脚本可能与你描述的问题和你给出的例子有什么关系,它完全不相关(但它可能对上述问题有意义在你的主题awk print full line before the matched pattern),所以这让我觉得你在这里描述的问题可能不够好。另外,您是字面上想从原始字符串的末尾删除字符串/scripts/boot,还是真的想删除最后两个路径段,无论它们的值如何? 您说 I rather use awk just to keep it consistent 但您发布的代码中没有 awk - 与什么一致? 如果您从/home/vMX-ENV/vMX-21.1R1/scripts/boot 中删除/scripts/boot,结果是/home/vMX-ENV/vMX-21.1R1,而不是/home/vMX-ENV/vMX-21.1R1/,请edit 您的问题是修复您要删除的字符串或预期的结果删除字符串。 对不起,我在深夜写了这条消息,我累了,我会澄清一下,我会更好!所以我有一个脚本有一个名为 SCRIPT_DIR 的变量,当我运行该命令时,我可以 echo $SCRIPT_DIR 打印出我的脚本所在的目录。当然 SCRIPT_DIR 是变量!对困惑感到抱歉。此外,如果有意义的话,我正在尝试使用 awk 从我的 echo 中删除字符串 /scripts/boot/ 【参考方案1】:

您的问题不清楚,但也许这就是您要尝试做的,即只需使用您的脚本所在目录上方 2 级目录的路径填充 SCRIPT_DIR?

SCRIPT_DIR="$( cd -- "$( dirname -- "$BASH_SOURCE[0]" )/../.." &> /dev/null && pwd )"

【讨论】:

对不起,我已经发布了一个更好的解释帖子,希望更有意义!谢谢你的回答,我今天到办公室后会试一试,我会告诉你的!【参考方案2】:

这是一个删除尾随部分的 AWK 命令:

$ echo /home/vMX-ENV/vMX-21.1R1/scripts/boot | awk 'match($0, "/scripts/boot$")  print substr($0, 1, RSTART - 1) '
/home/vMX-ENV/vMX-21.1R1

【讨论】:

awk 'sub("/scripts/boot$","") 会更简洁高效。 @EdMorton 确实!【参考方案3】:

您可以使用sed,而不是使用awk,如下所示:

echo /home/vMX-ENV/vMX-21.1R1/scripts/boot | sed 's/scripts\/boot$//'

这将为您提供输出:

/home/vMX-ENV/vMX-21.1R1/

【讨论】:

当您在正则表达式或替换字符串中有/s 时,您应该使用/ 以外的其他字符作为分隔符,这样您就不需要转义那些/s,例如sed 's:/scripts/boot$::'. @EdMorton:您的解决方案sed 's:/scripts/boot$::' 将给出/home/vMX-ENV/vMX-21.1R1 作为输出,没有尾随/,这不是PO 要求的。他想要/home/vMX-ENV/vMX-21.1R1/ 作为输出。见上文。 显然,如果您不想包含领先的 /,那就不要,这不是我评论的重点,但他们也说 I am trying to remove the /scripts/boot 所以请选择要求,因此my comment under the question. @EdMorton:我显然也同意您关于更改分隔符的评论。我只是选择了转义 /,以便让作为 PO 的新用户更容易理解我的 sed 命令。

以上是关于awk 在匹配模式之前打印整行的主要内容,如果未能解决你的问题,请参考以下文章

当第二列和第三列与数字模式匹配时打印整行

如何使用 awk 打印匹配的正则表达式模式?

使用 sed 或 awk 按照匹配模式打印一行

Linux AWK学习

awk 模式可以匹配多行吗?

使用 sed/awk 仅打印包含匹配模式的单词 - 以 /pattern/ 开头或以 /pattern/ 结尾的单词