我有以下文件(somefile.txt):
/A/1/B/1/C/1/D/1/E/1/F/2/G/1/H/1/I/1/J/1/K/1/
/B/1/C/1/D/1/E/1/F/5/G/1/H/1/I/1/J/1/K/1/
/C/1/D/1/E/1/F/9/G/1/H/1/I/1/J/1/K/1/
/D/1/E/1/F/7/G/1/H/1/I/1/J/1/K/1/
/A/1/B/1/C/1/D/1/E/1/F/8/G/1/H/1/I/1/J/1/K/1/
/A/1/B/1/C/1/D/1/E/1/F/3/G/1/H/1/I/1/J/1/K/1/
/A/1/B/1/C/1/D/1/E/1/F/6/G/1/H/1/I/1/J/1/K/1/
/B/1/C/1/D/1/E/1/F/8/G/1/H/1/I/1/J/1/K/1/
/D/1/E/1/F/3/G/1/H/1/I/1/J/1/K/1/
/C/1/D/1/E/1/F/6/G/1/H/1/I/1/J/1/K/1
我希望获得以下结果( 之后的下一个数字F
):
2
5
9
7
8
3
6
8
3
6
鉴于每行的列数是可变的,有没有办法可以执行以下操作?:
awk -F'/' '/F/ {print <column_of_match> + 1 }' somefile.txt
只需使用与分隔符和匹配的模式,
F
将该子字符串拆分为一个数组,然后打印该子字段。测试代码:
无需遍历字段,或使用两个进程。
您也可以通过调整字符串索引来删除不需要 , 的部分
split
,但这会降低它的通用性,并且更有可能出现一次性错误。将 GNU awk 用于多字符 RS:
使用 perl,因为数组切片很方便,所以能够将数组中的每对元素视为散列的键和值:
Perl
-F
和-a
(autosplit) 的工作方式与 awk 类似——但它不是将行自动拆分为 $1、$2、$3 等,而是将每一行自动拆分为一个名为@F
.该脚本将数组的
@F
一部分(除第零个元素外的所有元素)转换为名为 的散列(关联数组)%f
,并打印%f
带有键“F”的元素。为了强调这是做什么的/它是如何工作的(以及为什么我们需要排除@F 的空字符串第 0 个元素),下面是使用Data::Dump模块的函数时
@F
的%f
样子:dump
注意:如果输入中没有
F
,这将打印一个空行。如果那不是您想要的,请执行以下操作:这是一个使用的答案
sed
:解释
-n 's|.*F/\([0-9]\).*|\1|p'
:-n
表示除非明确告知,否则不要打印任何内容p
表示:“如果此表达式匹配,则打印此行”。这意味着F/[0-9]
不会打印没有的行。s|foo|bar|
在表达式中表示:替换foo
为bar
. 您通常将其视为s/foo/bar/
,但由于我们/
在表达式中有一个,我过去常常|
避免转义它。foo
):.*F/[0-9].*
表示:所有带有F/
数字的行。.*F/\([0-9]\).*
意思是:匹配包含F/
一个数字的整行,但记住那个数字bar
)中:\1
指的是我们记住的那个数字。简而言之:
*F/[0-9]*
,并仅将其替换为数字。如果多位正整数是可能的,那么表达式可以很容易地修改:
这是您的问题的可能解决方案,它涉及使用 awk 两次,一次用于在正确的位置拆分,下一次获取数字并打印出来。
这是脚本:
在第一部分中,我们将输入字符串拆分为
/F/
,这样第二部分的第一个字母就是我们要查找的数字,而在脚本的第二部分中,我们只是将这个数字隔离开来。这在我们每行最多有一个
F
时有效(它甚至在没有 F 时有效,因为它只会打印空行。