Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/backbone.js/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Bash 用sed删除除括号以外的所有内容,然后缩进_Bash_Sed_Awk_Tr - Fatal编程技术网

Bash 用sed删除除括号以外的所有内容,然后缩进

Bash 用sed删除除括号以外的所有内容,然后缩进,bash,sed,awk,tr,Bash,Sed,Awk,Tr,我有一个巨大的文件,一个非常巨大的文件(大约600+MB的文本)。事实上,它们是json。每个json都有一个新的行,并且只有几种口味 它们看起来像: {"text":{"some nested words":"Some more","something else":"Yeah more stuff","some list":["itemA","ItemB","itemEtc"]},"One last object":{"a thing":"and it's value"}} { -{ --[

我有一个巨大的文件,一个非常巨大的文件(大约600+MB的文本)。事实上,它们是
json
。每个
json
都有一个新的行,并且只有几种口味

它们看起来像:

{"text":{"some nested words":"Some more","something else":"Yeah more stuff","some list":["itemA","ItemB","itemEtc"]},"One last object":{"a thing":"and it's value"}}
{
-{
--[]
-}
-{
-}
}
我想要的是它通过sed,吸出文本,并为每一个nexted对放入一些缩进,因此我们得到:

{
 -{
--[]
 -}
--{}
 -}
}
(我不能100%确定我在输出上是否正确嵌套,我认为这是正确的)

这可能吗?我看到了,这是我能想象到的最接近的,但这去掉了两个括号

我注意到答案是使用分支,所以我想我需要它,我需要做一些
s/pattern/newline+tab/space/g
type命令,但我不知道如何或怎样做


有人能帮忙吗?它不必是纯粹的sed,但它更受欢迎。

这不太好…=)这是我作为sed脚本的解决方案。请注意,它要求第一行通知shell如何调用sed来执行脚本。如您所见,使用了“-n”标志,因此我们仅强制sed打印我们通过“p”或“p”命令显式命令它要打印的内容。“-f”选项告诉sed从文件中读取命令,并在选项后面加上名称。由于脚本的文件名由shell连接到最终命令中,它将正确地从脚本中读取命令(即,如果运行“/myscript.sed”,shell将执行“/bin/sed-nf myscript.sed”)

在我们开始之前,我们必须首先将所有内容分为方括号和方括号。这是第一个“s”司令部的职责。它告诉sed将所有不是方括号或方括号的字符替换为空,即删除它。请注意,匹配中的方括号表示要匹配的一组字符,但当其中的第一个字符是“^”时,它实际上将匹配除“^”之后指定的字符以外的任何字符。因为我们想要匹配结束方括号,并且我们需要用一个方括号结束要忽略的字符组,所以我们告诉您,结束方括号应该包含在组中,方法是使其成为“^”后面的第一个字符。然后我们可以指定其余的字符:开始方括号、开始方括号和结束方括号(一组被忽略的字符:“][{}”),然后用结束方括号结束该组

现在来看实际逻辑。算法非常简单:

while line isn't empty
    if line starts with optional spaces followed by [ or {
        if after the [ or { there are optional spaces followed by a respective ] or }
            print the respective pair, with only the indentation spaces, followed by a newline
        else
            print the opening square or normal bracket, followed by a newline
            remove what was printed from the pattern space (a.k.a. the buffer)
            add a space before every open or close bracket (normal or square)
        end-if
    else
        remove a space before every open or close bracket (normal or square)
        print the closing square or normal bracket, followed by a newline
        remove what was printed from the pattern space
    end-if
end-while
但是有两个怪癖。首先,sed不直接支持“while”循环或“if”语句。最接近的是“b”和“t”命令。“b”命令分支(跳转)到预定义的标签,类似于C goto语句。“t”也会分支到预定义的标签,但仅当在当前行上运行的脚本开始后或在上一个“t”命令后发生替换时才如此。标签使用“:”命令写入

因为第一个命令很可能实际执行至少一个替换,所以它后面的第一个“t”命令将导致分支。因为我们需要测试其他一些替换,我们需要确保下一个“t”命令不会因为第一个命令而自动成功。这就是为什么我们从“t”开始命令移到其正上方的一行(即,如果它是否分支,它仍将在同一点继续),因此我们可以“重置”由“t”命令使用的内部标志

因为“循环”标签将从至少一个“b”命令分支,所以在执行“b”时可能会设置相同的标志,因为只有“t”命令可以清除它。因此,我们需要执行相同的解决方法来重置标志,这次使用“虚拟”标签

现在,我们通过检查是否存在开方括号或开闭括号来启动算法。因为我们只想测试它们的存在,我们必须将匹配替换为自身,这就是“&”所表示的,sed将自动设置“t”的内部标志如果匹配成功,则使用“t”命令分支到“open”标签

如果不成功,我们需要查看是否匹配一个闭合正方形或括号中的法线。该命令几乎相同,但现在我们在闭合括号后附加一个换行符。我们通过在放置匹配项(即在“&”之后)后添加一个转义换行符(即反斜杠后跟实际换行符)来完成此操作与上述类似,如果匹配成功,我们使用“T”命令分支到“关闭”标签。如果它不成功,我们将认为行无效,并立即清空模式空间(缓冲器),并在下一行重新启动脚本,所有的都使用单个“D”命令。 输入“打开”标签,我们将首先处理一对匹配的开括号和闭括号的情况。如果我们确实匹配它们,我们将使用它们前面的缩进空格打印它们,中间没有空格,并以换行结束。每种类型的括号对(方形或普通)都有一个特定的命令,但它们是类似的。因为我们必须跟踪缩进空间的数量,我们必须将它们存储在一个特殊的“变量”中。我们通过使用组捕获来实现这一点,组捕获将存储匹配中在“(”之后开始并在“)之前结束的部分。因此,我们使用它来捕获行开始之后和开括号之前的空格。然后,我们继续匹配开括号后面的空格和相应的闭括号。写入替换时,我们确保使用特殊变量“\1”重新插入空格,其中包含匹配中第一个组捕获所存储的数据。然后,我们编写相应的开括号和闭括号对以及转义换行符

如果我们设法做了任何替换,我们必须打印我们刚刚写的内容
{
-{
--[]
-}
-{
-}
}
awk -f script.awk file.txt
BEGIN {
    FS=""
    flag = 0
}

{
    for (i=1; i<=NF; i++) {
        if ($i == "{" || $i == "[") {
            flag = flag + 1
            build_tree(flag, $i)
            printf (flag <=2) ? "\n" : ""
        }
        if ($i == "}" || $i == "]") {
            flag = flag - 1
            printf (flag >= 2) ? $i : \
                build_tree(flag + 1, $i); \
                printf "\n"
        }
    }
}

function build_tree (num, brace) {
    for (j=1; j<=num - 1; j++) {
        printf "-"
    }
    printf brace
}
sed 's/[^][{}]//g;s/./&\n/g;s/.$//' file |
sed -r '/[[{]/{G;s/(.)\n(.*)/\2\1/;x;s/^/\t/;x;b};x;s/.//;x;G;s/(.)\n(.*)/\2\1/' |
sed -r '$!N;s/((\{).*(\}))|((\[).*(\]))/\2\5\3\6/;P;D'