在bash中查找字符串的所有实例的字符位置

时间:2017-02-21 17:04:26

标签: string bash awk

我试图找到特定文件中字符串的所有实例的位置;但是,当前运行的代码I仅返回第一个实例的位置,然后停在那里。以下是我目前正在运行的内容:

str=$(cat temp1.txt) 
tmp="${str%%<C>*}"

if [ "$tmp" != "$str" ]; then
echo ${#tmp}
fi

该文件只有一行字符串,我会显示它,但格式问题需要在赢得不允许我在每个字符之间添加适当数量的空格。

2 个答案:

答案 0 :(得分:1)

我不确定您的要求的许多细节,但这是一个awk单行:

awk -vRS='<C>' '{printf("%u:",a+=length($0));a+=length(RS)}END{print ""}' temp1.txt

让我们用实际的输入线测试它:

$ awk -vRS='<C>' \
  '{printf("%u:",a+=length($0));a+=length(RS)}END{print ""}' \
   <<<"    <C>       <C>  "
4:14:20:

这意味着:第一个<C>位于字节4,第二个<C>位于第14个字节(包括第一个<C>的三个字节),整行为20字节长(包括最终换行符)。

这是你想要的吗?

<强> 解释

我们将(-v)记录分隔符(RS)设置为<C>。然后我们保留一个变量a,其中包含到目前为止处理的所有字节数。对于每个“行”(即<C> - 分隔的子字符串),我们将当前行的长度添加到aprintf使用合适的格式"%u:",并增加a乘以结束当前行的分隔符的长度。由于到目前为止还没有打印包含换行符,因此在END我们print一个空字符串,这是输出最终换行符的惯用语。

答案 1 :(得分:0)

查看this post提出的基本相同的问题。

特别是感谢用户,可以为多个实例回答您的问题 使用perl进行here响应。

编辑:我找到了另一种解决方案,可能就是这个技巧JRFerguson。 (主要问题和回复帖子是here。)

我将shell从ksh更改为bash,将搜索到的字符串更改为包含多个<C>以更好地演示问题的答案,并将其命名为“tester”:

 #!/bin/bash
printf '%s\n' '<C>abc<C>xyz<C>123456<C>zzz<C>' | awk -v s="$1" '
{       d = ""
        for(i = 1; x = index(substr($0, i), s); i = i + x + length(s) - 1) {
                printf("%s%d", d, i + x - 1)
                d = ":"
        }
        print ""
}'

这是我运行的方式:

$ tester '<C>'
1:7:13:22:28

我没有想出代码(我想知道它为什么有效)但它似乎工作!很高兴得到一个解释和一个优雅的方式来将您的字符串提供给此脚本。欢呼声。