我有一個制表符分隔的文本檔案,第一列包含要找到的單詞,第二列包含要替換找到的單詞的單詞。此文本檔案包含英語和阿拉伯語對。一旦找到并替換了該單詞,就不應再次更改它。
例如:
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
我該如何解決這個問題
uj5u.com熱心網友回復:
您的方法的基本問題是您不想將先前替換中的匹配文本替換為以后的替換 - 您不想將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' 在替換中評估替換文本的能力s///):
perl -e '
use strict;
use warnings;
# Set file/standard stream char encodings from locale
use open ":locale";
# Or for explicit UTF-8 text
# use open ":encoding(UTF-8)", ":std";
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
(這個會轉義要替換的單詞中的正則運算式元字符,使其更健壯)
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/413767.html
標籤:
下一篇:讀取用戶空間中ebpf的BPF_MAP_TYPE_HASH的更新值|可以使用read()linux函式獲取通過map共享的物件的當前值嗎
