与えられた単語を数値名に変換するコードを書こうとしています。
例: 国際化 = i18n (最初の文字 + 中間文字数 + 最後の文字)
最初の文字と最後の文字を見つける方法を見つけましたが、数字の部分を見つける方法もわかりますが、最初の文字と最後の文字の間に数字を入れる方法がわかりません。
数値部分を取得するために使用するコードは次のとおりです。
cut -c 2- | rev | cut -c 2- | rev | tr -d [:space:]| wc -c
最初の文字と最後の文字を取得するために使用するコードは次のとおりです。
awk -F "" '{print $1,$NF}'
答え1
空のフィールド区切り文字を使用することはやや「革新的」だと思いますが、awk
最も簡単な解決策は解決策の小さな拡張にすぎないと思います。
awk -F "" '{print $1 (NF-2) $NF}'
もちろん、これは3文字以上の単語にのみ適用されます。一般的な状況処理:
awk -F "" '{if (NF>2) print $1 (NF-2) $NF; else print $0}'
説明として:
-F ""
「$n
フィールド」を使用してフィールド区切り文字を「null」に設定するアッ表現(一緒にNは1から)までのフィールド番号ですNF
。ちなみに、GNU Awkユーザーガイドには明確に記載されています。これらのユースケースを例として提供してください。だから、空のFSの使用に関する以前の懸念を修正しました。しかし、マニュアルには「これは一般的な拡張であり、POSIX標準では指定されていません」と述べています。if
フィールド数(つまり、ここの文字数)が2より大きい場合は、最初のフィールド/文字($1
)、評価式(NF-2
)(最初と最後の間の文字数と同じ)、および最後のフィールドを印刷します。 /文字($NF
)。ここで使用されている呼び出しは、print
個々の出力トークン間にスペースを生成しません。これは、引数が空白ではなくカンマで区切られている場合にのみ発生します(参照)。例えば GNU Awkユーザーガイド)。else
次の方法でアクセスできる完全な入力式を印刷するだけです。$0
誤って2文字を入力した場合は、例えば at
、最初のコード例では、望ましくない(しかし正式には正しい)出力を取得しますa0t
(この場合、最初と最後の間に文字がゼロであるため)。
また参考にしてください、これは重要です。この呼び出しに先頭または末尾のスペースを含む文字列を指定するとawk
(たとえば、in)、対応するecho " hello" | awk <etc.>
先行/末尾のスペースが最初の/最後の文字として処理され、不要な動作が発生します。
答え2
ksh93、bashまたはzsh:
numeronym() {
(( ${#1} > 2 )) || return
printf '%s%d%s\n' "${1:0:1}" "$(( ${#1} - 2 ))" "${1: -1:1}"
}
これは最初の文字(文字数 - 2)と最後の文字を印刷して最初の(唯一の)引数を処理します。
答え3
別のawkソリューション:
awk '{l=length($1); print substr($1,1,1) l-2 substr($1,l,1)}'
l=length($1)
-l
変数を文字列の長さに設定します(入力文字列が最初の列にあり、スペースを含まないと仮定)。substr($1,1,1)
- (列番号、始点、終点) したがって、位置1から始まり、列1を印刷し、1文字を印刷します。l-2
- 文字列の長さを2だけ短くします。substr($1,l,1)
-l
位置(文字列の長さ)から始まり、列1を印刷して1文字を印刷します。
答え4
多くのシェルに移植可能:
a=internationalization;
if [ "${#a}" -gt 2 ]; then
a="${a%"${a#?}"}$((${#a}-2))${a#"${a%?}"}";
fi
printf '%s\n' "${a}"
機能的に(少し移植性が低い):
numeronym() { a="$1";
if [ "${#1}" -gt 2 ]; then
a="${a%"${a#?}"}$((${#a}-2))${a#"${a%?}"}";
fi;
printf '%s\n' "${a}";
}
呼ぶ:
$ numeronym internationalization
i18n
awkでなければならない場合:
$ echo internationalization |
awk '{ print (NF>2) ? $1 NF-2 $NF : $0 }' FS=''
i18n