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