在 Linux 中计算两个模式之间的模式总数(如果可能使用 sed)

Count total number of pattern between two pattern (using sed if possible) in Linux

我必须计算两个模式之间的所有“=”,即“{”和“}” 示例:

{
100="1";
101="2";
102="3";
}; 
{
104="1,2,3";
};
{
105="1,2,3";
};

预期输出:

3
1
1

Perl 来拯救:

perl -lne '$c = 0; $c += ("" =~ tr/=//) while /\{(.*?)\}/g; print $c' < input
  • -n逐行读取输入
  • -l 为每个 print
  • 添加一个换行符
  • /\{(.*?)\}/g 是正则表达式。 ? 使星号节俭,即匹配最短的字符串。
  • (...)括号创建一个捕获组,引用为</code>。</li> <li><code>tr一般用于音译(即用一个字符替换另一个字符),但这里只是统计等号的个数。
  • += 将数字添加到 $c.

一个非常神秘的 perl 答案:

perl -nE 's/\{(.*?)\}/ say ( =~ tr{=}{=}) /ge'

tr函数returns音译的字符数。


根据新要求,我们可以做一些小改动:

perl -0777 -nE 's/\{(.*?)\}/ say ( =~ tr{=}{=}) /ges'
  • -0777 将整个 file/stream 读入单个字符串
  • s/// 函数的 s 标志允许 . 像普通字符一样处理换行符。

awk 也来了

grep -o '{[^}]\+}'|awk -v FS='=' '{print NF-1}'

例子

echo '{100="1";101="2";102="3";}; 
{104="1,2,3";};
{105="1,2,3";};'|grep -o '{[^}]\+}'|awk -v FS='=' '{print NF-1}'

输出

3
1
1

首先是一些测试输入(大括号外和内容内有=的一行,一个没有括号,一个只有2个括号)

echo '== {100="1";101="2";102="3=3=3=3";} =; 
a=b
{c=d}
{}'

处理不带括号的行(放置一个虚拟字符,这样您就不会以空字符串结尾)

sed -e 's/^[^{]*$/x/' 

处理不带等号的行(放置一个虚拟字符,这样您就不会以空字符串结尾)

sed -e 's/{[^=]*}/x/' 

删除括号外的内容

sed -e 's/.*{\(.*\)}//'

删除双引号内的内容(不计算那里的字段)

sed -e 's/"[^"]*"//g' 

使用@repzero 方法计算等号

awk -F "=" '{print NF-1}'

合并东西

echo -e '{100="1";101="2";102="3";};\na=b\n{c=d}\n{}' | 
   sed -e 's/^[^{]*$/x/' -e 's/{[^=]*}/x/' -e 's/.*{\(.*\)}//' -e 's/"[^"]*"//g' | 
   awk -F "=" '{print NF-1}'

丑陋的临时字段 x 和替换 {} 可以在 awk 中解决:

echo -e '= {100="1";101="2=2=2=2";102="3";};\na=b\n{c=d}\n{}' | 
   sed -e 's/^[^{]*$//' -e 's/.*{\(.*\)}//' -e 's/"[^"]*"//g' | 
   awk -F "=" '{if (NF>0) c=NF-1; else c=0; print c}'

或更短

echo -e '= {100="1";101="2=2=2=2";102="3";};\na=b\n{c=d}\n{}' |
   sed -e 's/^[^{]*$//' -e 's/.*{\(.*\)}//' -e 's/"[^"]*"//g' |
   awk -F "=" '{print (NF>0) ? NF-1 : 0; }'

不难 sed 完成...在.

将此答案限制在标记的环境中,即:

实际上不需要使用 (或 awkperl 或任何其他应用程序)。

虽然使用了echo,但文件源很容易排除它的使用。
至于bash,就是.

最后记录了实际使用的环境

NB. Exploitation of GNU specific extensions has been used for brevity
    but appropriately annotated to make a more generic implementation.
    Also brace bracketed { text } will not include braces in the text.
    It is implicit that such braces should be present as {} pairs but
    the text src. dangling brace does not directly violate this tenet.
This is a foray into the world of `sed`'ng to gain some fluency in it's use for other purposes.
The ideas expounded upon here are used to cross pollinate another SO problem solution in order
to aquire more familiarity with vetting vagaries of vernacular version variances. Consequently
this pedantic exercice hopefully helps with the pedagogy of others beyond personal edification.

To test easily, at least in the environment noted below, judiciously highlight the appropriate 
code section, carefully excluding a dangling pipe |, and then, to a CLI command line interface
drag & drop, copy & paste or use middle click to enter the code.

The other SO problem. linux - Is it possible to do simple arithmetic in sed addresses?

# _______________________________ always needed ________________________________

echo -e '\n
\n   = = = {\n              }  = = =                each = is outside the braces
\na\nb\n   {                }                       so therefore are not counted
\nc\n      { = = = = = = =  }                       while the ones here do count
           {\n100="1";\n101="2";\n102="3";\n};                  
\n         {\n104="1,2,3";\n};                                  
a\nb\nc\n  {\n105="1,2,3";\n};                                  
           {   dangling brace ignored junk =  = = \n'  |     

# _____________ prepatory conditioning needed for final solutions _____________

sed                ' s/{/\n{\n/g;                               
                     s/}/\n}\n/g; '       |  # guarantee but one brace to a line

sed -n '/{/               h;                 # so sed addressing can "work" here
        /{/,/}/           H;                 # use hHold buffer for only { ... }
            /}/   { x; s/[^=]*//g; p } '  |  # then make each {} set a line of =
# ____ stop code hi-lite selection in  ^--^ here  include quote not pipe ____

# ____ outputs the following exclusive of the shell " # " comment quotes _____
   # 
   # 
   # =======
   # ===
   # =
   # =
# _________________________________________________________________________

# ____________________________ "simple" GNU solution ____________________________

sed -e '/^$/  { s//0/;b };                    # handle null data as 0 case: next!
                s/=/\n/g;                     # to easily count an = make it a nl
                s/\n$//g;                     # echo adds an extra nl - delete it
                s/.*/echo "&" | sed -n $=/;   # sed = command w/ $ counts last nl
                e '                           # who knew only GNU say you ah phoo

   # 0
   # 0
   # 7
   # 3
   # 1
   # 1
# _________________________________________________________________________

# ________________________ generic incomplete "solution" ________________________

sed -e '/^$/ { s//echo 0/;b };                # handle null data as 0 case: next!
               s/=$//g;                       # echo adds an extra nl - delete it
               s/=/\\n/g;                   # to easily count an = make it a nl
               s/.*/echo -e & | sed -n $=/; '                 

# _______________________________________________________________________________

用于该算法的范例是由下面的序言研究发起的。
这个想法是将 = 符号组隔离在 { } 大括号之间进行计数。
找到这些,每组都放在单独的一行上,并删除所有其他装饰字符。
需要注意的是 sed 可以很容易地“计数”,实际上枚举 nl 或 \n 行结束于 =.

第一个“解决方案”使用这些 sed 命令:

  • p打印
  • b牧场w/o标签开始新的循环
  • h/H旧用于填充此 sed 缓冲区
  • ex改变保持和模式缓冲区
  • =枚举当前sed输入行
  • ss/.../.../;替换为g局部标志s/.../.../g;

尤其是 GNU 特定的

  • evaluate(execute记不住实际助记词但无关紧要的同义词)

通用代码中避免了 GNU 特定的 execute 命令。它不打印答案但是 而是生成将打印答案的代码。 运行 观察一下吧。为了完全自动化,许多 可以使用一些机制,其中最重要的是 sed write 命令将这些行放在 shell 要执行的文件,甚至将输出嵌入 bash 评估括号 $( )

另请注意,各种 sed 示例脚本可以“计数”,并且这些脚本也可以有效地使用。

有兴趣的 reader 可以考虑这些其他的追求。


导言: 计算大括号之间行数的概念

sed -n '/{/=;/}/=;' 

sed -n  '/}/=;/{/=;'              | 
sed -n  'h;n;G;s/\n/ - /;
         2s/^/ Between sets of {} \n the nl # count is\n     /;
         2!s/^/     /;
         p'

测试“完成”:

linuxuser@ubuntu:~$  lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 18.04.2 LTS
Release:        18.04
Codename:       bionic

linuxuser@ubuntu:~$  sed --version   ----->  sed (GNU sed) 4.4

还有一个 awk 唯一的替代方案:

echo '{
> 100="1";
> 101="2";
> 102="3";
> }; 
> {
> 104="1,2,3";
> };
> {
> 105="1,2,3";
> };' | awk 'BEGIN{RS="\n};";FS="\n"}{c=gsub(/=/,""); if(NF>2){print c}}'
3
1
1