たぶんvimなしの方が簡単です:
1回だけ出現させたい行が正規表現「aregexp」と一致する場合、
grep "$aregexp" file | head -n 1 > /tmp/thatline #first occurence of the line.
all_other_occurences="$(fgrep -n "$(cat /tmp/thatline)" file | head -n +2 | tac)"
#fgrep string file : search string in file, literrally, without using regexp
#head -n +2 (or on some machines: head -n +1) skips the 1st line of the input
#tac : so that we have line numbers in reverse order (allowing to delete them without moving the next ones up!)
#here add a test to see if all_other_occurence is empty : nothing to do then (there was no lines other than the first one)
#otherwise:
for linetodelete in "$all_other_occurence" ; do
# either delete line n in file using sed -i,
# or create&concatenate a vim command that later will be used to
# delete those lines from inside vim, via script or copy/paste manually...
done
別のアプローチ(おそらくより高速です!):すべての行を削除し、最初の出現箇所を適切な場所に再挿入します
thelinenumber=$( awk '$0~var{print NR;exit}' var="$aregexp" < file)
#will exit as soon as it finds the 1st occurence
theline="$(sed -e "${thelinenumber}p" < file)"
fgrep -v "$theline" file > newfile #delete all occurence
awk -v l="$thelinenumber" -v s="$theline" 'NR == l {print s} {print}' file > file.new
私はそれらをチェックしませんでしたが、意図を確認し、構文の問題を修正できることを願っています(そして、空の変数のダブルチェック、行が1つだけあるかどうかのテストなどを追加します)