简体   繁体   English

Linux:如何替换文件中包含引号和逗号的文本字符串

[英]Linux: How to replace a string of text containing quotes and commas in a file

I'm not the greatest with awk, perl, or sed, and I can't figure out how to replace a string of text in a file. 我不是awk,perl或sed的佼佼者,而且我不知道如何替换文件中的文本字符串。

The string is somewhat unusual. 该字符串有点不寻常。 Actually, there are 2 of them I need to replace in 1 file automatically. 实际上,有2个文件需要我自动替换为1个文件。

The file contains a single line of text, very long, in JSON format. 该文件包含一行很长的JSON格式的文本。 Per-line replacements won't work. 每行替换将不起作用。

Here is the text I need to replace. 这是我需要替换的文字。 From: 从:

"minimumVersion":2,"librariesLocation":"libraries","objectsLocation":"objects",

to

"minimumVersion":2,"librariesLocation":"pack/libraries","objectsLocation":"pack/objects",

As you can see there are quotes in the text and slashes I need to enter, as well as commas and multiple occurences of libraries and objects, making my current knowledge of sed, awk, and perl useless. 如您所见,在文本中需要输入引号和斜杠,以及逗号和库和对象的多次出现,这使我目前对sed,awk和perl的了解毫无用处。

How can I add the 'pack/' prefix to the text 'libraries' and 'objects'? 如何在文本“库”和“对象”中添加“ pack /”前缀?

Please don't try and use regex for JSON. 请不要尝试对JSON使用正则表达式。 It's nasty. 真讨厌 Use a JSON parser: 使用JSON解析器:

#!/usr/bin/env perl

use strict;
use warnings;
use JSON; 

my $json_str = '{ "minimumVersion":2,"librariesLocation":"libraries","objectsLocation":"objects" }';

my $json_ob = decode_json($json_str);

print "Before:", $json_ob -> {'librariesLocation'},"\n";

#pattern replace just the values we're interested in.
$json_ob -> {'librariesLocation'} =~ s,^,pack/,;
$json_ob -> {'objectsLocation'} =~ s,^,pack/,;

print "After: ", $json_ob -> {'librariesLocation'},"\n";

#print single line text blob
print encode_json($json_ob);
print "\n\n";

## or perhaps (formatted, multiline, whitespace):

print to_json($json_ob, { canonical => 1, pretty => 1 } );

This works with the rough sample - if you want a better one, give me more JSON and I'll redraft. 这适用于粗略示例-如果您想要更好的示例,请给我更多JSON,然后我将重新起草。

This outputs: 输出:

Before:libraries
After: pack/libraries
{"objectsLocation":"pack/objects","minimumVersion":2,"librariesLocation":"pack/libraries"}

{
   "librariesLocation" : "pack/libraries",
   "minimumVersion" : 2,
   "objectsLocation" : "pack/objects"
}

Edit: To do this from a file: 编辑:要从文件中执行此操作:

local $/; 
open ( my $input, '<', 'source_filename_here' ) or die $!;
open ( my $output, '>', 'output_filename_here' ) or die $!;

my $json_ob = decode_json(<$input>);
#do the transforms

print {$output} encode_json($json_ob); 

Or alternatively (reading from STDIN printing to STDOUT just like sed/grep etc.): 或者(从sed / grep等从STDIN打印读取到STDOUT):

#!/usr/bin/env perl

use strict;
use warnings;
use JSON;

my @stuff_to_change = qw ( librariesLocation objectsLocation );

local $/;

#read from stdin or arg on commmand line. E.g.:
#myscript.pl somefile
#cat json_file | myscript.pl
my $json_ob = decode_json(<>);

#pattern replace just the values we're interested in.
for my $thing (@stuff_to_change) {
    $json_ob->{$thing} =~ s,^,pack/,;
}

#print single line text blob to STDOUT
print encode_json($json_ob);

How can I add the 'pack/' prefix to the text 'libraries' and 'objects'? 如何在文本“库”和“对象”中添加“ pack /”前缀?

How about a simple sed command: 一个简单的sed命令如何:

echo '"minimumVersion":2,"librariesLocation":"libraries","objectsLocation":"objects",' > file

sed 's~"\(libraries\|objects\)"~"pack/\1"~g' file

Output: 输出:

"minimumVersion":2,"librariesLocation":"pack/libraries","objectsLocation":"pack/objects",

To run over ssh: 要运行ssh:

ssh ip<<'EOF'
sed -i 's~"libraries"~"pack/&"~; s~"objects"~"pack/&"~' file.json 
EOF

sed --in-place will do the trick, with the correct escaping sed-就地将完成正确的转义

$ echo '"minimumVersion":2,"librariesLocation":"libraries","objectsLocation":"objects",' > text.txt      
$ sed --in-place 's/"\(libraries\|objects\)"/"pack\/\1"/g' text.txt
$ cat text.txt 
  "minimumVersion":2,"librariesLocation":"pack/libraries","objectsLocation":"pack/objects",

replace pattern "libraries" with "pack/libraries" (using grouping and reuse of matching pattern) "pack/libraries"替换模式"libraries" (使用分组和匹配模式的重用)

With proper JSON input, you could use jq : 通过正确的JSON输入,您可以使用jq

$ jq '.librariesLocation |= "pack/"+., .objectsLocation |= "pack/"+.' <<EOF
{"minimumVersion":2,"librariesLocation":"libraries","objectsLocation":"objects"}
EOF
{
  "minimumVersion": 2,
  "librariesLocation": "pack/libraries",
  "objectsLocation": "objects"
}
{
  "minimumVersion": 2,
  "librariesLocation": "libraries",
  "objectsLocation": "pack/objects"
}

If your input is just a comma-separated list of key/value pairs, you might be able to use jq to turn it into a proper JSON object before filtering, but I don't know jq well enough yet to figure out how. 如果输入仅仅是一个逗号分隔的键/值对的列表,你也许可以使用jq滤波前把它变成一个正确的JSON对象,但我不知道jq不够好,还没有弄清楚如何。

awk '{gsub(/libraries",|objects",/, "pack/&")}1' file
minimumVersion":2,"librariesLocation":"pack/libraries","objectsLocation":"pack/objects",

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM