我有 abc.txt 文件,其中包含两行。我想提取包含db
特定行中的单词的行中的第一个单词。
abc.txt:
XYZ/db_abc.sql
ijkl/tables/table_name/tl_abc.sql
当我尝试 grep 时,grep "db" abc.txt
我得到包含“db”的行,但我想提取第一个单词XYZ
作为输出。
输出:
$ grep "db" abc.txt
XYZ/db_abc.sql
预期输出:
XYZ
同样,当我尝试 grep 时,grep "tl" abc.txt
我得到包含“tl”的行,但我想提取第三个单词table_name
作为输出。
输出:
$ grep "tl" abc.txt
ijkl/tables/table_name/tl_abc.sql
预期输出:
table_name
答案1
$ awk -F / -v q=db '$0 ~ q { print $(NF-1) }' file
XYZ
$ awk -F / -v q=tl '$0 ~ q { print $(NF-1) }' file
table_name
这两个awk
命令是相同的,但给出了不同的参数来查询不同的表达式。在命令行上分配给awk
变量的任何字符串都q
将用作扩展正则表达式,并将与给定文件中的每一行进行匹配。当表达式与一行匹配时,将打印从末尾算起的第二个字段。这是通过使用特殊变量NF
(当前行的字段数)来计算倒数第二个字段的字段号 ( NF-1
) 来完成的。该实用程序通过斜杠分隔字段(如使用 所示-F /
)。
其变体可确保查询模式仅在最后一个字段中匹配:
awk -F / -v q=tl '$NF ~ q { print $(NF-1) }' file
另外确保我们只关心以 结尾的行.sql
:
awk -F / -v q=tl '/\.sql$/ && $NF ~ q { print $(NF-1) }' file
答案2
它会返回整行,因为 grep 默认情况下是这样工作的。要提取句子的某个部分,我建议您使用正则表达式。
要提取XYZ
句子,您可以使用如下构建的正则表达式:
grep -oP ".*(?=/db) abc.txt"
-o
是只返回与模式匹配的行。
-P
是使用 来搜索模式Perl Regex
。
.*
搜索除以下字符之外的任何字符\n
(?=/db)
会说寻找匹配字符串后面的所有内容,/db
但一旦到达字符串本身就停止匹配。意思是,不包括/db
以及除此之外的任何东西。
类似地,为了寻找,table_name
我们需要应用类似的方法。我们可以像这样使用正则表达式:
grep -oP "(?<=tables/).*(?=/tl) abc.txt"
这与上一个 grep 有点相似,但这次我们添加了(?<=tables/)
它,告诉 grep 返回 之前tabels/
和之后的任何内容/tl
。
awk
如果您不想使用正则表达式,我们也可以通过使用命令来完成此操作。
要检索XYZ
您可以使用:
grep "db" abc.txt | awk -F '/' '{ print $1 }'
因此,在这种情况下,该grep
命令将返回整行,但我们使用awk
分隔符来分割该行/
,并返回分割行的第一部分。
要检索table_name
我们可以这样做:
grep "tl" abc.txt | awk -F '/' '{ print $3 }'
这与第一个命令非常相似,但在这种情况下我们需要句子的第三部分。