在下面的示例中,我将变量$ line设置为“ 14”,它与文件的第14行即“第四”相关。
我需要在BASH中找到一种方法,以从($ line)(14)中设置的行号开始,并找到同一文件中下一次出现的字符串(foo)的行号。在这种情况下,结果将是第16行。
one
foo
bar
foo
two
foo
three
foo
foo
bar
foo
foo
foo
four
bar
foo
bar
five
foo
six
foo
foo
bar
foo
$line = "14"
$search = "foo"
答案 0 :(得分:2)
很多方法可以做到这一点。但是,如果您想单独使用bash进行操作(即不使用awk,perl等),则可以采用以下一种方法:
$ mapfile -t -O 1 a < ttt
$ for ((i=$line; i<=${#a[@]}; i++)); do [[ "${a[$i]}" = "$string" ]] && echo "$i" && break; done
mapfile
命令将文件吸收到一个数组中(以比循环中的read
更好的方式),而-O 1
使它开始从1开始对数组索引编号而不是0。for循环从$line
开始,以[[
遍历数组,该数组将当前数组值与$string
进行比较。
我仍然很想知道您提出了什么解决方案,并帮助您了解为什么它行不通。
答案 1 :(得分:1)
尝试awk:
line=14
search=foo
awk '(NR > n && $0 == s){ print NR; exit }' n=$line s="$search" file
输出:
16
您可以通过以下方式将结果分配给变量:
declare -i var=$(awk '(NR > n && $0 == s){ print NR; exit }' n=$line s="$search" file)
答案 2 :(得分:1)
sed
单线-
使用您的数据,将其命名为“ infile”,我得到
$: line=14 search=foo sed -n $line,\${/$search/\{=\;q}} infile
16
这将在执行sed
之前为env设置变量,并告诉它不要输出-n
尚未提出的任何内容。
命令$line,\${/$search/\{=\;q}}
的计算结果为14,${/foo/{=;q}}
这意味着“从第14行到末尾,找到其中包含“ foo”的下一行,然后
打印行号(
=
)并退出(
q
),而不处理文件的其余部分。