我正在尝试编写一个bash脚本来修改文件中某个字符串的所有匹配项。
我有一个包含大量文本的文件,其中包含网址。所有网址都采用以下格式:http://goo.gl/abc23
(即goo.gl/,后跟4或5个字母数字字符)。
我想做的是在所有网址上附加一个字符串。我设法(在用户Dan Fego的帮助下)使用sed完成此操作,但它只能通过附加静态字符串来实现。
我正在寻找的方法是为每次出现添加不同的字符串。假设我有一个函数generatestring
,每次都会回显一个不同的字符串。我想为每个网址添加不同的生成字符串。 http://goo.gl/abc23
将成为http://goo.gl/abc23?GeneratedString1
,http://goo.gl/JB007
将成为http://goo.gl/JB007?GeneratedString2
,依此类推。
有谁知道这是否可以做到?我被告知perl是要走的路,但我对perl没有经验。这就是我在这里问的原因。
提前感谢您的帮助。
答案 0 :(得分:2)
ETA:假设网址嵌入在其他文字中:
$ perl -lnwe 's#http://goo.gl/\w{5}\K\b# "?" . rand(100) #ge; print' googl.txt
例如:
$ cat googl
random text here, and perhaps some html <a href="http://goo.gl/abc23">
more stuff http://goo.gl/abc23 foo fake link http://foo.bar/abc12
longer http://goo.gl/abc23123123 foo fake link http://foo.bar/abc12
$ perl -lnwe 's#http://goo.gl/\w{5}\K\b# "?" . rand(100) #ge; print' googl
random text here, and perhaps some html <a href="http://goo.gl/abc23?69.998515">
more stuff http://goo.gl/abc23?26.186867532985 foo fake link http://foo.bar/abc12
longer http://goo.gl/abc23123123 foo fake link http://foo.bar/abc12
-l
chomps
该文件并向print.
添加换行符-n
在脚本周围添加while(<>)
循环,这基本上意味着它从参数文件中读取名字或来自STDIN。 \K
表示“保留匹配的文字”,\b
是字边界,因此您不匹配部分字符串。
请注意它仍会匹配http://goo.gl/abc12/foo
,但由于我不知道您的数据是什么样的,因此您必须确定可接受的边界。
当然,rand(100)
只是作为您打算使用的任何功能的占位符。
如果您需要脚本版本,请参阅解压缩代码:
use strict;
use warnings;
BEGIN { $/ = "\n"; $\ = "\n"; }
while (<>) {
chomp;
s[http://goo.gl/\w{5}\K\b]['?' . rand(100);]eg;
print;
}
答案 1 :(得分:1)
你可以用很多语言来做,但在Perl中它非常简单:
#!/usr/bin/perl
use strict;
use constant MAX_RANDOM_STRING_LENGTH => 5;
my $regex_url = '(http://goo.gl/\w{5})';
my @alphanumeric = ("A".."Z", "0".."9");
my $random_cap = $#alphanumeric + 1;
sub generate_string
{
my $string = "?";
for (my $i = 0; $i < MAX_RANDOM_STRING_LENGTH; $i++)
{
$string .= $alphanumeric[int(rand($random_cap))];
}
return $string;
}
my @input = <>;
for(@input)
{
my $cur = $_;
while ($cur =~ /$regex_url/)
{
$cur = $';
my $new_url = $1 . generate_string();
s/$1/$new_url/g;
}
}
print(@input);
用法:
script_name.pl < input.txt > output.txt
答案 2 :(得分:1)
如果每行中的URL不是唯一的,您可以执行以下操作:
#!/usr/bin/perl
use strict;
use warnings;
sub generate {
my $i = shift;
return "GeneratedString$i";
}
my $i = 0;
while(my $line = <>) {
$line =~ s~(http://\S+)~$1 . "?" . &generate($i++)~eg;
print $line;
}
<强>用法:强>
test.pl file_to__modify
<强>输出:强>
http://goo.gl/abc23?GeneratedString1
http://goo.gl/JB007?GeneratedString2
答案 3 :(得分:0)
这可能对您有用:
gs(){ echo $(tr -cd '[:alnum:]' </dev/urandom | head -c5); }
export -f gs
cat <<\! file
> http://goo.gl/abc23
> http://goo.gl/JB007
> bunch of text http://goo.gl/qwert another bunch of text
> another bot http://goo.gl/qwert another bot http://goo.gl/qaza
!
sed '\|http://goo\.gl/[0-9a-zA-Z]\{4,5\}\>|{s//&?'\''$(gs)'\''/g;s/^/echo '\''/;s/$/'\''/}' file |
sh
http://goo.gl/abc23?0Az23
http://goo.gl/JB007?ugczB
bunch of text http://goo.gl/qwert?LDW27 another bunch of text
another bot http://goo.gl/qwert?U9my2 another bot http://goo.gl/qaza?Ybtlp