[英]Find and replace words using sed command not working
我有一個制表符分隔的文本文件,第一列包含要找到的單詞,第二列包含要替換找到的單詞的單詞。 一旦找到並替換了該單詞,就不應再次更改它。
例如:
adam a +dam
a b
所以對於給定的文本文件:
adam played with a ball
我預計:
a +dam played with b ball
但是,我得到:
b +dbm plbyed with b bbll
我正在使用以下 sed 命令來查找和替換:
sed -e 's/^/s%/' -e 's/\t/%/' -e 's/$/%g/' tab_sep_file.txt | sed -f - original_file.txt >replaced.txt
我該如何解決這個問題
您的方法的基本問題是您不想將先前替換中的匹配文本替換為以后的替換 - 您不想將a +dam中的 a 更改為b 。 這使得sed
成為一個非常糟糕的選擇 - 你可以創建一個匹配所有你想要替換的東西的正則表達式,但是選擇使用哪個替換是一個問題。
一種使用 GNU awk
的方法:
gawk -F'\t' '
FNR == NR { subs[$1] = $2; next } # populate the array of substitutions
ENDFILE {
if (FILENAME == ARGV[1]) {
# Build a regular expression of things to substitute
subre = "\\<("
first=0
for (s in subs)
subre = sprintf("%s%s%s", subre, first++ ? "|" : "", s)
subre = sprintf("%s)\\>", subre)
}
}
{
# Do the substitution
nwords = patsplit($0, words, subre, between)
printf "%s", between[0]
for (n = 1; n <= nwords; n++)
printf "%s%s", subs[words[n]], between[n]
printf "\n"
}
' tab_sep_file.txt original_file.txt
哪個輸出
a +dam played with b ball
首先,它讀取 TSV 文件並構建要替換的單詞數組和替換為 ( subs
) 的文本。 然后在讀取該文件后,它會構建一個正則表達式來匹配所有可能找到的單詞 - 在這種情況下是\<(a|adam)\>
。 \<
和\>
僅分別匹配單詞的開頭和結尾,因此球中的a將不匹配。
然后對於包含要處理的文本的第二個文件,它使用patsplit()
將每一行拆分為匹配部分( words
)和匹配之間的位( between
)的數組,並迭代數組的長度,打印輸出每個匹配項的替換文本。 這樣可以避免重新匹配已經被替換的文本。
還有一個使用相同方法的perl
版本:
perl -e '
my %subs;
open my $words, "<", shift or die $!;
while (<$words>) {
chomp;
my ($word, $rep) = split "\t" ,$_, 2;
$subs{$word} = $rep;
}
my $subre = "\\b(?:" . join("|", map { quotemeta } keys %subs) . ")\\b";
while (<<>>) {
print s/$subre/$subs{$&}/egr;
}
' tab_sep_file.txt original_file.txt
(這個會轉義要替換的單詞中的正則表達式元字符,使其更健壯)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.