注:すでに同様の質問がありました。AWK:ソース用語の後にターゲット単語を挿入する簡単な方法そして私はAWKの初級レベルです。
この問題は、ランダムに選択された複数行のソース用語の後に複数のターゲット用語を挿入することを考慮しています。
このAWKコードスニペットを使用すると、
awk '(NR==FNR){a[$1];next}
FNR in a { gsub(/\<source term\>/,"& target term") }
1
' <(shuf -n 5 -i 1-$(wc -l < file)) file
5つのランダム行target term
の後に1つを挿入したいと思います。source term
file
例:dict
左側にソース用語が含まれ、右側にターゲット用語が含まれるバイリンガル辞書があります。
apple : Apfel
banana : Banane
raspberry : Himbeere
鉱山はfile
次の行で構成されています。
I love the Raspberry Pi.
The monkey loves eating a banana.
Who wants an apple pi?
Apple pen... pineapple pen... pen-pineapple-apple-pen!
The banana is tasty and healthy.
An apple a day keeps the doctor away.
Which fruit is tastes better: raspberry or strawberry?
最初の単語apple
に対してランダムな行1、3、5、4、7が選択されているとします。 appleという単語を含む出力は次のとおりです。
I love the Raspberry Pi.
The monkey loves eating a banana.
Who wants an apple Apfel pi?
Apple Apfel pen... pineapple pen... pen-pineapple-apple-pen!
The banana is tasty and healthy.
An apple a day keeps the doctor away.
Which fruit is tastes better: raspberry or strawberry?
banana
その後、選択する単語に5つのランダムな行が追加されます。
I love the Raspberry Pi .
The monkey loves eating a banana .
Who wants an apple Apfel pi ?
Apple Apfel pen... pineapple pen... pen-pineapple-apple-pen!
The banana Banane is tasty and healthy .
An apple a day keeps the doctor away .
Which fruit is tastes better: raspberry or strawberry?
dict
他のすべての項目は、最後の項目が一致するまで続きます。
ランダムに5本のラインを選びたいです。行に完全なソース用語が含まれている場合は、単語全体をapple
一致させようとします(「pineapple」などの用語は無視されます)。たとえば、1行にソース用語が2回含まれている場合は、その後にターゲット用語を挿入したいと思います。一致は大文字と小文字を区別する必要があるため、同じソース用語も一致させることができます。Apfel
apple
apple
apple
Apple
dict
私の質問:辞書が利用可能で辞書を選択できるように、上記のコードスニペットをどのように書き換えますか?ランダム行をクリックfile
し、ソース用語の後にターゲット用語を挿入しますか?
答え1
以下は、awkを使用して入力ファイル内の5つの行番号をランダムに選択する方法です(最初のパスでwcを使用すると行番号のみが計算されます)。
$ awk -v numLines="$(wc -l < file)" 'BEGIN{srand(); for (i=1; i<=5; i++) print int(1+rand()*numLines)}'
7
2
88
13
18
もう持って行けばいい私の以前の答えブロックから読み取られた各「前の」文字列について、ARGIND==1
上記のように5つの行番号を生成し、配列を埋め、生成された行番号を各行番号に関連付けられている前の文字列にマップし、ファイルを読み込みます。最後に、ファイルが入力されたら確認します。行番号が現在の配列にあり、そうである場合は、その行番号の配列に格納されている「前」を繰り返し、前の回答gsub()
で示した操作を実行します。
ARGIND
、、IGNORECASE
単語の境界、配列の配列、および:の省略形\s
を表すには、GNU awkを使用します。[[:space:]]
$ cat tst.sh
#!/usr/bin/env bash
awk -v numLines=$(wc -l < file) '
BEGIN {
FS = "\\s*:\\s*"
IGNORECASE = 1
srand()
}
ARGIND == 1 {
old = "\\<" $1 "\\>"
new = "& " $2
for (i=1; i<=5; i++) {
lineNr = int(1+rand()*numLines)
map[lineNr][old] = new
}
next
}
FNR in map {
for ( old in map[FNR] ) {
new = map[FNR][old]
gsub(old,new)
}
}
{ print }
' dict file
$ ./tst.sh
I love the Raspberry Pi.
The monkey loves eating a banana Banane.
Who wants an apple Apfel pi?
Apple Apfel pen... pineapple pen... pen-pineapple-apple Apfel-pen!
The banana Banane is tasty and healthy.
An apple a day keeps the doctor away.
Which fruit is tastes better: raspberry Himbeere or strawberry?
答え2
拡張正規表現モード (-E) および s/// コマンドの (/e) 修飾子を使用する GNU sed:
n=$(< file wc -l)
sed -E '/\n/ba
s#^(\S+)\s*:\s*(\S+)$#s/\\<\1\\>/\& \2/Ig#;h'"
s/.*/shuf -n 5 -i '1-$n'/e;G
:a
s/^([0-9]+)(\n.*\n(.*))/\1 \3\2/
/\n.*\n/!s/\n/ /
P;D
" dict | sed -f /dev/stdin file
- ダクトファイルの内容からGNU sedコマンドを生成します。
- コマンドを保留状態に保存します。
- サイコロを振り、入力ファイルの行の長さ内に5つの乱数を生成します。
- 保存モードに固執し、これらの特定の行でのみ実行されるsedコマンドを生成します。
- 入力ファイルに生成された次のコマンドを適用します。