文字列の前から文字を「ドロップ」/削除する方法は?


12

操作したい文字列があります。文字列はH08W2345678どのように操作できるのW2345678ですか?出力はちょうどですか?

同様に、最後の4文字を削除して、どうすればH08W2345678これを取得できるH08W234ようにしたいのですか?


1
文字列を操作するには多くの方法があります。使用する特定の理由はありsedますか?
don_crissti

@don_crissti経験不足以外は理由はありません。どんな代替案も歓迎します...
3kstc 2015

@don_crissti、ストーリー:フィルターされたCSVファイルから、ある行からパラメーターの1つを取得し、H08W2345678それを次のように操作する必要がありますW2345678。メール送信はcronで行われます。
2015

@don_crisstiing awkit。私は配列を作成してから、配列内の各要素を変更します(すべて異なる方法で、つまり秒単位のエポックタイムスタンプを日付に変更します)
3kstc

2
そのようなことをawkで行うことができます:printf %s\\n "XX,H08W2345678,YY" | awk -F, '{print substr($2, 4); print substr($2, 1, length($2)-4)}'
don_crissti

回答:


18

単にbashを使用する(またはksh93その構文がどこから来るかzsh):

string="H08W2345678"

echo "${string:3}"
W2345678

echo "${string:0:-4}"
H08W234

文字列操作の詳細については、Wooledge wikiを参照してください。


これには、bash 4.2以降が必要です。参照してくださいバッシュリファレンスマニュアルのこの古いコピー、3.5.3項を、「」シェルパラメータ展開「」またはここで雛の答えは、古い制約を参照してください(「長さよりも数値以上に評価したり、ゼロに等しくなければなりません。」); …(続き)
Scott

(続き)… Bashの変更(Bash Hackers Wikiで)(セクションの一番下までスクロールしてください)またはCase Western Reserve UniversityのTechnology Infrastructure Services組織でのbashニュースを参照(「added to bash-4.2」で検索)次に「q。」までスクロールして、リビジョンを確認します。………… "${string:0:${#string}-4}" の長さが$string4以上である限り、bashバージョン4.1で動作します 
Scott

PSこれはまたabc-e、最初の3文字をドロップしたときに残されたのような文字列を窒息させます(望みどおりに動作しない-eためecho -e)。
スコット

8
$ echo "H08W2345678" | sed 's/^.\{3\}//'
W2345678

sed 's/^.\{3\}//'最初の3文字を検索し、^.\{3\}空白に置き換えます。ここで^.は、文字列の先頭にある任意の文字(文字列^の先頭を示す)と\{3\}一致し、前のパターンと正確に3回一致します。したがって、^.\{3\}最初の3文字と一致します。

$ echo "H08W2345678" | sed 's/.\{4\}$//'
H08W234

同様に、sed 's/.\{4\}$//'最後の4文字を空白で置き換えます($文字列の終わりを示します)。


1
あなたは説明してもらえます's/^.\{3\}//'し、's/.\{4\}$//'私はまだセッド、多くのおかげで勉強していて
3kstc

@ 3kstc:編集内容を確認してください
heemayl

1
ほんの数文字について....\{3\}、それ以降(私にとっては)読みやすくする代わりに、sed -e 's/^...//' -e 's/....$//' または単一の式を交互に使用して使用しますsed -r 's/^...|....$//g'。削除する文字が数文字以上の場合は、の/.\{17}\/代わりに式を使用します/.............../
ジョニー

文字列が-eまたはの場合、これは正しく動作しません-n。もちろん、「最後の4文字をドロップする」の意味は4文字より短い文字列では定義されていませんが、誰かがこれを最初または最後の1文字をドロップするように適応させようとすると、爆発する可能性があります。
スコット

2

すべての行が11文字(または何でも)の文字列であるファイルを持っている場合、それ sedが使用するツールです。単一の文字列を操作する場合は問題ありませんが、やり過ぎです。単一の文字列の場合、bashバージョン4.2以降にアクセスできる場合、Jasonの答えがおそらく最良です。ただし、 および構文はbashに固有のようです(まあ、bash、ksh93、mksh、およびzsh)— シェルコマンド言語のOpen Group Base仕様には表示されません。サブストリング拡張(抽出)をサポートしないPOSIX準拠のシェルでスタックしている場合は、次を使用できます。${parameter:offset}${parameter:offset:length}

$ printf "%s\n" "${string#???}"
W2345678

$ printf "%s\n" "${string%????}"
H08W234

printfではなく、echoを使用してabc-e、最初の3文字をドロップすると、残りの文字列を保護します-eecho -e必要な操作を行いません)。

また、Bourneファミリシェルをまったく使用していない場合(または、古く、POSIX以前のシステムを使用している場合)でも、これらは動作するはずです。

$ expr " $string" : ' ...\(.*\)'
W2345678

$ expr " $string" : ' \(.*\)....'
H08W234

余分な先頭のスペースは、の値に問題がないようにすることです$string 実際であることexpr演算子(例えば、+、  /、  indexまたはmatch)やオプションを(例えば、  ----helpまたは  --version)。


@StéphaneChazelas:(1)私が約40年前に知っていて、どういうわけか忘れることができた落とし穴を思い出させてくれてありがとう。(2)私はいつもこれを使ってこれを解決していましたX; 例えば、expr "X$string" : 'X...\(.*\)'。IMO、それは読みやすく理解しやすいです。それで問題はありませんか、それともスペースを好む理由がありますか?(3)今日、私はexpr + "$string" : '...\(.*\)'今それがうまくいくことを学びました。40年前から覚えていません。安全に推奨するのに十分広く使用されていますか?(4)jasonwryanの回答についてのメモとheemaylの回答についての抜粋を逃しました。
スコット

AFAIK、それexpr +はGNUのみです(SolarisやFreeBSD AFAICSでは機能しません)。xの代わりにスペースを使用します。一部のexpr実装では、スペースで始まる演算子がで始まるx可能性が低く、スペースで始まる照合要素がある場合よりも少ないためxです。しかし、expr " $a" "<" " $b"一部の実装は$a/が数値の$bように見える場合に数値比較を行うため、文字列比較にはおそらく適していないことに気づきました。多分expr "@@$a"...またはexpr "x $a"より安全かもしれません。
ステファンChazelas

0

と:

string="H08W2345678"

3文字または4文字の一致は単純なようです(ほとんどのシェルの場合)。

$ printf '%s\t%s\n' "${string#???}" "${string%????}"
W2345678      H08W234

古いシェル(Bourneシェルなど)の場合は、次を使用します。

$ string=H08W2345678

$ expr " ${string}" : " ...\(.*\)"
W2345678

$ expr " ${string}" : " \(.*\)...." '
H08W234

文字の数値カウントが必要な場合は、以下を使用します。

$ expr " ${string}" : " .\{3\}\(.*\)"
W2345678

$ expr " ${string}" : " \(.*\).\{4\}" '
H08W234

もちろん、これらの正規表現はsed、awk、bash 3.0以降でも機能します。

$ echo "$string" | sed 's/^.\{3\}//'
W2345678

$ echo "$string" | sed 's/.\{4\}$//'
H08W234

$ echo "$string" | awk '{sub(/^.{3}/,"")}1'
W2345678

$ echo "$string" | awk '{sub(/.{4}$/,"")}1'
H08W234

$ r='^.{3}(.*)$'; [[ $a =~ $r ]] && echo "${BASH_REMATCH[1]}"
W2345678

$ r='^(.*).{4}$'; [[ $a =~ $r ]] && echo "${BASH_REMATCH[1]}"
H08W234

-1

文字列の前から文字を「ドロップ」/削除する方法は?

操作したい文字列があります。文字列はH08W2345678です。出力をW2345678にするにはどうすれば操作できますか?

echo "H08W2345678" | cut -c 4-

これは質問の半分しか答えません。
クサラナンダ

あなたの反対票は不公平だと思います。この半分は、posixをグーグル検索して最初の文字削除し、このページが検索結果に表示されたときの質問答えます。さらに、このページのタイトルは、質問の正確な半分だけをカバーしています。私が戻ってきて、気に入った解決策を見つけたときに貢献しました。その仕事は、このページの他のどのソリューションよりもはるかにエレガントだと思います。cut
aexl
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.