我正在尝试基于标记缩进文件的几个级别。 标记参数仅表示下一个单词相同 line是第二级标记。基于这个二级标记, 我想缩小所有内容,直到下一次出现 二级标记。
我尝试这样做的原因是为了调试另一个应用程序。我在顶部和每个函数返回之前打印出数据(以及其间的几个部分)。
提前致谢!
用法是这样的: ./script.sh文件标记
示例数据:
data
thismarker m1
thismarker m2
data
data
thismarker m2
data
data
thismarker m1
data
./script.sh文件的所需输出此标记:
data
data
thismarker m1
thismarker m2
data
data
thismarker m2
data
data
thismarker m1
data
这是我到目前为止所拥有的。我目前正在使用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
}
'
答案 0 :(得分:2)
使用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
包含一堆匹配的标记。答案 1 :(得分:2)
$ 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
请注意,我修改了您的示例输入文件,以显示m1
范围内的m2
在m1
范围内sed
的情况,因为这通常会在函数中发生调用它使解决方案比不需要考虑更复杂。考虑到输入,我当前发布的perl
解决方案将失败,我当前的UNIX框中没有{{1}},我无法开始猜测当前发布的perl咒语是什么,所以我已经不知道这是否有效 - 如果你有perl就试试。
答案 2 :(得分:1)
您需要管理一堆关卡才能正确处理。在伪代码中
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
答案 3 :(得分:0)
sed '/thismarker m1/,/thismarker m1/{
/thismarker m1/!s/^/ /
/thismarker m2/,/thismarker m2/{
/thismarker m2/!s/^/ /
}
}' YourFile
相同的概念,如果几个级别(只是在最后一级结束之前添加新的部分)
/thismarker mX/,/thismarker mX/{
/thismarker mX/!s/^/ /
}
说明:
在相同引用的2个标记之间(/thismarker mX/,/thismarker mX/
)[标记不在同一行,它是必需的,但请求由它的结构指定],对于没有特定的每一行标记(/thismarker mX/ !
),用3个空格(s/^/ /
)替换行的开头。
第二级以相同的方式完成,但在&#34;循环内#34;第一级。第三级应该在&#34;循环中做同样的事情。二等等...