perl/awk/sed/bash脚本:具有多个标记的多个缩进级别

perl/awk/sed/bash脚本:具有多个标记的多个缩进级别,perl,bash,shell,awk,sed,Perl,Bash,Shell,Awk,Sed,我正在尝试根据标记将文件缩进几个级别。 marker参数只表示同一个单词上的下一个单词 直线是第二级标记。基于这个二级标记, 我想把所有东西都缩进,直到下一次出现这种情况 二级标记 我尝试这样做的原因是为了调试另一个应用程序。我将在每个函数返回之前打印出顶部的数据(以及中间的一些内容) 提前谢谢 用法如下: ./script.sh文件标记 示例数据: /script.sh文件thismarker的所需输出: 这是我到目前为止所拥有的。我目前正在使用awk,但我对任何有效的东西都很满意。但是,它不

我正在尝试根据标记将文件缩进几个级别。 marker参数只表示同一个单词上的下一个单词 直线是第二级标记。基于这个二级标记, 我想把所有东西都缩进,直到下一次出现这种情况 二级标记

我尝试这样做的原因是为了调试另一个应用程序。我将在每个函数返回之前打印出顶部的数据(以及中间的一些内容)

提前谢谢

用法如下: ./script.sh文件标记

示例数据:

/script.sh文件thismarker的所需输出:

这是我到目前为止所拥有的。我目前正在使用awk,但我对任何有效的东西都很满意。但是,它不适用于多个级别,我不知道如何使用mymarkertwo来代替我目前正在做的工作——硬编码hcmarkertwo

#!/bin/bash                                                                      

file_path=$1                                                                     
markerone=$2                                                                     

 cat ${file_path} | awk -v mone="$markerone" '                                    
    BEGIN {                                                                  
            get_out=0;                                                       
            myfunc="";                                                       
    } {                                                                      

            if ( /${mone}/ ) {                                               
                    mymarkertwo = $2                                         
            }                                                                

            if ( /hcmarkertwo/ ) {                                           
                    get_out=0                                                
                    print $0                                                 
                    getline                                                  

                    do {                                                     
                            if ( /hcmarkertwo/ ) {                           
                                    get_out = 1                              
                                    print $0                                 
                                    getline                                  
                            } else {                                         
                                    $0 = "\t"$0                              
                                    print $0                                 
                                    getline                                  
                            }                                                
                    } while ( get_out == 0 )                                 
            }                                                                
    print $0                                                                 
}
'

您需要管理一堆级别,以便正确处理此问题。伪码

line <- file.read
if line.words[0] == "thismarker"
    if line == stack.top
      stack.pop
      print(indent=stack.size) line
    else
      print(indent=stack.size) line
      stack.push(line)
    endif
 else
   print(indent=stack.size) line
endif

line您需要管理一堆级别,以便正确处理此问题。伪码

line <- file.read
if line.words[0] == "thismarker"
    if line == stack.top
      stack.pop
      print(indent=stack.size) line
    else
      print(indent=stack.size) line
      stack.push(line)
    endif
 else
   print(indent=stack.size) line
endif
行
如果有多个级别,则概念相同(只需在最后一个级别结束之前添加一个新部分)

说明:

在相同引用的两个标记(
/thismarker mX/,/thismarker mX/
)[标记不在同一行上,这是必需的,但要求通过其结构指定它],对于没有特定标记(
/thismarker mX/!
)的每一行,用3个空格(
s/^/
)替换行的开头。 第二个级别是以相同的方式完成的,但在第一个级别的“循环”内。第三级应该在第二级的“循环”内做同样的事情,等等

如果有多个级别,则概念相同(只需在最后一个级别结束之前添加一个新部分)

说明:

在相同引用的两个标记(
/thismarker mX/,/thismarker mX/
)[标记不在同一行上,这是必需的,但要求通过其结构指定它],对于没有特定标记(
/thismarker mX/!
)的每一行,用3个空格(
s/^/
)替换行的开头。
第二个级别是以相同的方式完成的,但在第一个级别的“循环”内。thrd级别应该在第二级别的“循环”内执行相同的操作,等等…

使用perl one liner:

perl -lne '
    ($m) = $_ =~ /thismarker (\S+)/;
    pop(@M), $m = "" if $m && @M && $M[-1] eq $m;
    print +("   " x @M), $_;
    push @M, $m if $m;
  ' file.txt
说明: 开关

  • -l
    :启用行结束处理,指定行结束符
  • -n
    :为输入文件中的每一行创建
    while(){..}
    循环
  • -e
    :告诉
    perl
    在命令行上执行代码
代码

  • $m
    包含当前行的匹配标记:
    'm1'
    'm2'
  • @M
    包含一组匹配的标记

使用perl一行程序:

perl -lne '
    ($m) = $_ =~ /thismarker (\S+)/;
    pop(@M), $m = "" if $m && @M && $M[-1] eq $m;
    print +("   " x @M), $_;
    push @M, $m if $m;
  ' file.txt
说明: 开关

  • -l
    :启用行结束处理,指定行结束符
  • -n
    :为输入文件中的每一行创建
    while(){..}
    循环
  • -e
    :告诉
    perl
    在命令行上执行代码
代码

  • $m
    包含当前行的匹配标记:
    'm1'
    'm2'
  • @M
    包含一组匹配的标记

请注意,我修改了示例输入文件,以显示一种情况,即
m1
m2
的范围内,在以前的
m1
的范围内,这通常会发生在函数调用中,这使得解决方案比不需要考虑的情况更加复杂。当前发布的
sed
解决方案将失败,因为输入了该信息,我当前的UNIX设备上没有
perl
,我无法猜到当前发布的perl咒语是怎么说的,所以我不知道这是否有效-如果您有perl,请尝试一下


请注意,我修改了示例输入文件,以显示一种情况,即
m1
m2
的范围内,在以前的
m1
的范围内,这通常会发生在函数调用中,这使得解决方案比不需要考虑的情况更加复杂。鉴于该输入,当前发布的
sed
解决方案将失败,我当前的UNIX设备上没有
perl
,我无法猜到当前发布的perl咒语是怎么说的,所以我不知道这是否有效-如果您有perl,请尝试一下。

重要问题:标记+标签是否需要成对出现?通过
m1
m2
开口标记的嵌套缩进级别是否可以由第二次出现的顶级标记
m1
终止?(如果没有,那么额外的
m1
m2
标签是多余的。)使用
getline
通常是错误的(在本例中是错误的)-如果您将来考虑使用它,请阅读并完全理解。感谢大家提供了一些很棒的答案!是的,标记和标签总是成对出现。重要问题:标记和标签是否需要成对出现?通过
m1
m2
开口标记的嵌套缩进级别是否可以由第二次出现的顶级标记
m1
终止?(如果没有,那么额外的
m1
m2
标签是多余的。)使用
getline
通常是错误的(在本例中是错误的)-如果您将来考虑使用它,请阅读并完全理解。感谢大家提供了一些很棒的答案!是的,标记和标签总是成对出现。直接添加在post中直接添加在post中
一行
?我在cygwin上安装了Perl5.14.4以尝试上述操作,并获得了
语法分析器
/thismarker mX/,/thismarker mX/{
   /thismarker mX/!s/^/   /
   }
perl -lne '
    ($m) = $_ =~ /thismarker (\S+)/;
    pop(@M), $m = "" if $m && @M && $M[-1] eq $m;
    print +("   " x @M), $_;
    push @M, $m if $m;
  ' file.txt
$ cat tst.awk
$1 == marker {
    if ($2 == markerId[depth]) {
        --depth
        nextIndent = --indent
    }
    else {
        markerId[++depth] = $2
        nextIndent = indent + 1
    }
}
{
    printf "%*s%s\n",indent,"",$0
    indent = nextIndent
}
$ cat file
data
thismarker m1
thismarker m2
data
thismarker m1
data
data
thismarker m1
data
thismarker m2
data
data
thismarker m1
data
$ awk -v marker="thismarker" -f tst.awk file
data
thismarker m1
 thismarker m2
  data
  thismarker m1
   data
   data
  thismarker m1
  data
 thismarker m2
 data
 data
thismarker m1
data