行がある場合:
There are seven pencil
次のように印刷したいと思います。
Ther a svn pcil
Bashシェルコマンドとは何ですか?
説明:目標は、複数回出現するすべての文字(最初の文字を除く)を削除することです。
答え1
s/replace-this/with-that/g
グローバル置換=すべての発生を意味するsedの古典的な構文に基づいて、誰かがwhich(拡張)の代わりにg
whichを使用できます。2g
g
global replacement but after second occurence
gnu sed
削除のみの例e
:
$ echo $a
there are seven pencil
$ echo $a | sed 's/e//2g'
ther ar svn pncil
すべての重複文字を削除するには、次のトリックを使用できます。
$ sed -f <(printf 's/%s//2g\n' {a..z}) <<<"$a"
ther a svn pcil
残念ながら、これは機能しません。sed 's/[a-z]//2g'
上記のトリックは、ファイル<( )
として使用できるプロセス置換を使用します。
私の解決策では、手続き型置換はsed
option = read sedコマンドを介してファイルから提供されたスクリプトファイルとして扱われます。sed
-f
答え2
Awk
回避策(大文字と小文字の区別):
s="There are seven pencil"
printf '%s\n' "$s" | awk -v FS="" '{
for(i=1; i<=NF; i++)
if ($i==" " || !a[$i]++) printf "%s", $i; print ""
}'
-v FS=""
- 各文字が別々のフィールドになるように「空」フィールド区切り文字を設定します(POSIXではなく多くの実装でサポートされているGNU拡張)。for(i=1; i<=NF; i++)
- 文字の繰り返しif ($i==" " || !a[$i]++)
- 空白文字または初登場する文字の場合
出力:
Ther a svn pcil
大文字と小文字を区別しないようにするには、a[$i]
に置き換えますa[tolower($i)]
。
答え3
これはBashそのものです。
s="There are seven pencil"
declare -A A
while IFS= read -rn1 a; do
[ -z "$a" ] || [ -n "${A[$a]}" ] && continue
printf %s "$a"
[ "$a" == " " ] || A[$a]=x
done <<<"$s"
echo
1行ずつ説明:
変数に文字列を割り当てる
s="There are seven pencil"
連想配列宣言
A
declare -A A
これは少し複雑です。ただし、詳細がない場合は、個々の文字ごとに文字列を読み取り、読み取ったばかりの文字をに割り当てます
a
。これはwhile
サイクルです。while IFS= read -rn1 a; do
現在の文字が空の場合(
[ -z "$a" ]
)または(||
)このキー(この文字)に関連する値が設定されている場合(設定されている場合はここに表示されます)、ループを続行します(次の繰り返しに進みます。次の内容をお読みください)。文字)を再印刷せずに続行します)。[ -z "$a" ] || [ -n "${A[$a]}" ] && continue
現在の文字を印刷します。
printf %s "$a"
文字が空白の場合は実行されません。
A[$a]=x
これが||
ここで意味するものです。A[$a]=x
関連タスクです。すべてのスペースを避けるために、配列のキースペースに値を割り当てないでくださいA
。 (4番項目参照)[ "$a" == " " ] || A[$a]=x
これにより
while
サイクルが終了する。<<<"$s"
ここに文字列リダイレクトがあります。ループを文字列で埋めます。done <<<"$s"
最後に、
echo
行区切り文字を印刷します。printf
5番の項目では文字のみ印刷されます。これがなければ、echo
出力は次のシェルプロンプトと同じ行に表示されます。それを脱いで自分で確認してください。echo
答え4
別のsed
解決策:
単一のアルファベット文字の場合:
$ echo 'here hear' | sed 's/\(\([[:alpha:]]\).*\)\2/\1' here ear
これらのすべてに対して
g
すでに処理されている文字は再確認されないため、このフラグは役に立ちません。したがって、ループを使用すると、「t」は交換が成功する限りラベルに分岐します。$ echo There are seven pencils | sed -e :a -e 's/\(\([[:alpha:]]\).*\)\2/\1/; ta' Ther a svn pcil
GNUを使用すると、
sed
次のように短縮できます。sed -E ':a;s/(([[:alpha:]]).*)\2/\1;ta'
大文字と小文字を無視(まだGNUを使用sed
):
$ echo 'There this That' | sed -E ':a; s/(([[:alpha:]]).*)\2/\1/i; ta'
Ther is a
そのうちperl
(ASCII文字はここでのみ):
$ echo 'There are seven pencil' | perl -pe 'while(s/([a-zA-Z]).*?\K\1//g){}'
Ther a svn pcil
$ echo 'There this That' | perl -pe 'while(s/([a-z]).*?\K\1//gi){}'
Ther is a