使用Perl、sed、awk替换多行模式

4
我需要连接多个JSON文件,因此
        ...
        "tag" : "description"
    }
]
[
    {
        "tag" : "description"
        ...

将其翻译为中文:将此转换为:
    ...
    "tag" : "description"
},
{
    "tag" : "description"
    ...

我需要将模式] [替换为,,但换行符让我很困扰...

我使用了几种方法,以下是其中一些:

  • sed

     sed -i '/]/,/[/{s/./,/g}' file.json
    

    but I get this error:

    sed: -e expression #1, char 16: unterminated address regex
    
  • I tried to delete all the newlines following this example

    sed -i ':a;N;$!ba;s/\n/ /g' file.json
    

    and the output file has "^M". Although I modified this file in unix, I used the dos2unix command on this file but nothing happens. I tried then to include the special character "^M" on the search but with worse results

  • Perl (as proposed here)

    perl -i -0pe 's/]\n[/\n,/' file.json
    

    but I get this error:

    Unmatched [ in regex; marked by <-- HERE in m/]\n[ <-- HERE / at -e line 1.
    

直接字符串操作是您唯一的选择吗?为什么不解析每个文件中的JSON,并使用perl-core JSON模块处理结果并将其写出呢? - SREagle
我可能误解了你的问题,但是:你第一个示例行的内容是你自己做出来的结果(“我想连接几个JSON文件。”),还是已经在其中一个文件中给出的事实?如果是后者,请忽略我的第一个评论。 - SREagle
][之间的JSON对象是从哪里来的?换句话说,您目前是如何合并这些文件的? - Windle
@SREagle 抱歉,我认为管理员删掉了我的问题。 ...}][{ .. 是两个JSON文件连接的结果。然后,SREagle,您的建议是一种可能性,但我认为最后一个要连接的文件仍然存在问题。 - buondi
@buondi:你尝试使用过jq吗?它是专门用来处理JSON文件的。这个命令行就足够了:jq -c -s -r '[.[]|.[]]' file.json > result.json - Casimir et Hippolyte
3个回答

2
我想要连接几个JSON文件。如果我理解正确,您有类似以下的内容(其中字母代表有效的JSON值):
to_combine/file1.json: [a,b,c]
to_combine/file2.json: [d,e,f]

然后,你想得到以下内容:

combined.json: [a,b,c,d,e,f]

你可以使用以下方法来实现这个目标:
perl -MJSON::XS -0777ne'
   push @data, @{ decode_json($_) };
   END { print encode_json(\@data); }
' to_combine/*.json >combined.json

关于你的Perl解决方案中出现的问题:
  1. [在正则表达式模式中有特殊含义,需要进行转义。
  2. 你只进行了一次替换。
  3. -0并没有真正打开 slurp 模式。应该使用 -0777
  4. 你将逗号放在换行符之后,如果放在换行符之前会更好。
修复方法:
cat to_combine/*.json | perl -0777pe's/\]\n\[/,\n/g' >combined.json

1
请注意,更好的合并多个JSON文件的方法是解析它们所有,组合解析后的数据结构,并重新编码结果。仅仅将所有][替换为逗号,可能会改变数据而不是标记。
sed是一个最小化程序,只能一次操作文件的单行。Perl包含了sed或awk所能做的一切,还有很多其他功能,因此建议您坚持使用它。
要将file.json中所有]...[对(可能由空格分隔)更改为单个逗号,请使用以下内容。
perl -0777 -pe "s/\]\s*\[/,/g" file.json > file2.json

-0选项指定八进制行分隔符,并将其值设置为777,使perl一次性读取整个文件

一行代码通常难以理解,我总是更喜欢一个适当的程序文件,它看起来像这样

join_brackets.pl

use strict;
use warnings 'all';

my $data = do {
    local $/;
    <>;
}

$data =~ s/ \] \s* \[ /,/gx;

print $data;

and you would run it as

perl join_brackets.pl file.json > joined.json

0

我尝试使用你问题中的示例。

$ sed -rn '
    1{$!N;$!N}
    $!N
    /\s*}\s*\n\s*]\s*\n\s*\[\s*\n\s*\{\s*/M { 
        s//\},\n\{/
        $!N;$!N 
    }
    P;D
' file
        ...
        "tag" : "description"
},
{
        "tag" : "description"
        ...
        ...
        "tag" : "description"
},
{
        "tag" : "description"
        ...

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接