[英]Using sed on text files with a csv
我一直在嘗試使用csv對兩個文本文件進行批量查找和替換。 我已經看到了SO提出的問題,但似乎沒有人回答我的問題。
我為要修改的兩個文本文件創建了兩個變量。 CSV具有兩列和幾百行。 第一列包含文本文件中已經存在的字符串(沒有空格),需要用第二列同一行中的相應字符串替換。
作為測試,我嘗試了腳本
#!/bin/bash
test1='long_file_name.txt'
find='string1'
replace='string2'
sed -e "s/$find/$replace/g" $test1 > $test1.tmp && mv $test1.tmp $test1
這是成功的,除了我需要使用每行中csv給定的值對csv中的每一行執行一次。 我的直覺是我的while循環被錯誤地使用,但是我找不到錯誤。 當我執行下面的腳本時,我得到命令行提示符,這使我認為事情已經發生了。 當我檢查文本文件時,沒有任何改變。
這兩個文本文件,此腳本和csv都在同一文件夾中(當我執行此操作時,這也是我的工作目錄)。
#!/bin/bash
textfile1='long_file_name1.txt'
textfile2='long_file_name2.txt'
while IFS=, read f1 f2
do
sed -e "s/$f1/$f2/g" $textfile1 > $textfile1.tmp && \
mv $textfile1.tmp $textfile1
sed -e "s/$f1/$f2/g" $textfile2 > $textfile2.tmp && \
mv $textfile2.tmp $textfile2
done <'findreplace.csv'
在我看來,這段代碼應該按照我想要的去做(但不是); 也許我誤解了一些基本知識(我是bash腳本的新手)?
csv看起來像這樣,但是有數百行。 在下一列中,所有a_i應替換為其對應的b_i。
a_1 b_1
a_2 b_2
a_3 b_3
注意事項:所有字符串實際上都包含下划線,以防萬一這會影響某些內容。 我試過將變量名用大括號$ {var}括起來,但是仍然不起作用。
我很欣賞這些解決方案,但也很想知道為什么上述方法不起作用。 (此外,我會投票給所有人,但我沒有這樣做的聲譽。但是,請注意,我很感激,並從您的回答中學到很多東西!
如果您要處理大量數據,並且您的模式可以包含特殊字符,我會考慮使用Perl。 尤其是在findreplace.csv
要有很多對的findreplace.csv
。 您可以使用以下腳本作為篩選器或對很多文件進行就地修改。 副作用是,它每次調用僅加載一次替換並創建Aho-Corrasic自動機,這將使該解決方案非常有效(解決方案中的O(M+N)
而不是O(M*N)
)。
#!/usr/bin/perl
use strict;
use warnings;
use autodie;
my $in_place = ( @ARGV and $ARGV[0] =~ /^-i(.*)/ )
? do {
shift;
my $backup_extension = $1;
my $backup_name = $backup_extension =~ /\*/
? sub { ( my $fn = $backup_extension ) =~ s/\*/$_[0]/; $fn }
: sub { shift . $backup_extension };
my $oldargv = '-';
sub {
if ( $ARGV ne $oldargv ) {
rename( $ARGV, $backup_name->($ARGV) );
open( ARGVOUT, '>', $ARGV );
select(ARGVOUT);
$oldargv = $ARGV;
}
};
}
: sub { };
die "$0: File with replacements required." unless @ARGV;
my ( $re, %replace );
do {
my $filename = shift;
open my $fh, '<', $filename;
%replace = map { chomp; split ',', $_, 2 } <$fh>;
close $fh;
$re = join '|', map quotemeta, keys %replace;
$re = qr/($re)/;
};
while (<>) {
$in_place->();
s/$re/$replace{$1}/g;
}
continue {print}
用法:
./replace.pl replace.csv <file.in >file.out
以及
./replace.pl replace.csv file.in >file.out
或就地
./replace.pl -i replace.csv file1.csv file2.csv file3.csv
或帶備份
./replace.pl -i.orig replace.csv file1.csv file2.csv file3.csv
或帶備用絲毫占位符
./replace.pl -ithere.is.\*.original replace.csv file1.csv file2.csv file3.csv
您應該使用以下命令將CSV文件轉換為sed.script:
cat replace.csv | awk -F, '{print "s/" $1 "/" $2 "/g";}' > sed.script
然后,您將可以進行一次通行證更換:
sed -i -f sed.script longfilename.txt
這將是您想做的事的更快實現。
順便說一句,對不起,但是我不明白您的腳本有什么問題,該腳本應該可以工作,除非您的CSV文件有兩列以上。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.