2016-11-18 6 views
1

なぜ次のbashコードが動作しないのですか?文字列をbashの複数文字区切り文字に分割する方法は?

for i in $(echo "emmbbmmaaddsb" | split -t "mm" ) 
do 
    echo "$i" 
done 

予想される出力:

e 
bb 
aaddsb 
+1

からBash Tutorial?それは「分割」がまったく何をするのではない。 **実際の機能とは完全に無関係です**。 –

+0

bashの任意の複数文字の区切り文字に任意の文字列を分割する方法を知りたいですか?あなたが本当に知りたいことがあれば、その質問を編集するのはなぜですか? –

+0

@CharlesDuffyあなたの意見で分裂は何をするのですか? – v217

答えて

5

あなたは改行を期待しているので、あなたは単に改行を使用して文字列内のmmのすべてのインスタンスを置き換えることができます。純粋なネイティブbashで:

in='emmbbmmaaddsb' 
sep='mm' 
printf '%s\n' "${in//$sep/$'\n'}" 

あなたが長く、入力ストリーム上にそのような交換をしたいと思った場合はbashの組み込みの文字列操作がにうまくスケールしないよう、あなたは、awkを使用したほうが良いかもしれません数キロバイト以上のコンテンツ​​で与えられる(awkにbackending)gsub_literalシェル関数を適用することが可能である:

# Taken from http://mywiki.wooledge.org/BashFAQ/021 

# usage: gsub_literal STR REP 
# replaces all instances of STR with REP. reads from stdin and writes to stdout. 
gsub_literal() { 
    # STR cannot be empty 
    [[ $1 ]] || return 

    # string manip needed to escape '\'s, so awk doesn't expand '\n' and such 
    awk -v str="${1//\\/\\\\}" -v rep="${2//\\/\\\\}" ' 
    # get the length of the search string 
    BEGIN { 
     len = length(str); 
    } 

    { 
     # empty the output string 
     out = ""; 

     # continue looping while the search string is in the line 
     while (i = index($0, str)) { 
     # append everything up to the search string, and the replacement string 
     out = out substr($0, 1, i-1) rep; 

     # remove everything up to and including the first instance of the 
     # search string from the line 
     $0 = substr($0, i + len); 
     } 

     # append whatever is left 
     out = out $0; 

     print out; 
    } 
    ' 
} 

...ように、この文脈において、使用される:bashので

gsub_literal "mm" $'\n' <your-input-file.txt >your-output-file.txt 
2

s="emmbbmmaaddsb" 
for i in "${s//mm/$'\n'}"; do echo "$i"; done 

出力:

 
e 
bb 
aaddsb 
+0

これは何も分割しません... 'mm'を改行で置き換えるだけです。 'echo $ {s // m/$ '\ n'}' 'を実行して' for'ループを完全に削除することもできます。 –

+0

@gniourf_gniourf:私は質問者がすべての行で何かをしたいと思っていました。 – Cyrus

+0

しかし、あなたが書いた方法である 'for'ループは、各行でループしません。単一の文字列 '$ 'e \ nbb \ naaddsb'で一回のみループします。 –

0

文字のサブタイトルに推奨されるツールは、正規表現の場合はsedのコマンドs/regexp/replacement/、グローバルの場合はs/regexp/replacement/gです。ループや変数は必要ありません。

パイプあなたのecho出力と改行文字\n witht文字にmmを代用してみてください:出力がある

echo "emmbbmmaaddsb" | sed 's/mm/\n/g'

e 
bb 
aaddsb 
+0

「推奨」ですか? bashの文字列操作に関するベストプラクティスのガイダンスについては、[BashFAQ#100](http://mywiki.wooledge.org/BashFAQ/100)を参照してください。パラメータの拡張は一般的に、短い入力に対してはベストプラクティスのアプローチと見なされます(ただし、 'echo | sed 'アプローチは簡潔ではあるが、それがどのように実装されているかという点でオーバーヘッドが大きい)典型的には2つのフォーク、mkfifo、リンクとロードが必要な外部ツールの 'execv'など)が必要です。 –

+0

...タイトなループで入力を1行ずつ処理している場合(または、数百または数千のファイル名を含むグロブ結果を反復処理する場合)、 'echo |各行に対して「sed」は絶対に反パターンになります。 (入力ストリーム全体を処理する 'sed' *を1回だけ呼び出す*とは対照的に、しばしば適切です)。 –

2

より一般的な例として、マルチを交換することなく、単一の文字区切り文字を持つ-character delimiterは次のとおりです。

パラメータ拡張を使用:リファレンス

#!/bin/bash 

# main string 
str="LearnABCtoABCSplitABCaABCString" 

# delimiter string 
delimiter="ABC" 

#length of main string 
strLen=${#str} 
#length of delimiter string 
dLen=${#delimiter} 

#iterator for length of string 
i=0 
#length tracker for ongoing substring 
wordLen=0 
#starting position for ongoing substring 
strP=0 

array=() 
while [ $i -lt $strLen ]; do 
    if [ $delimiter == ${str:$i:$dLen} ]; then 
     array+=(${str:strP:$wordLen}) 
     strP=$((i + dLen)) 
     wordLen=0 
     i=$((i + dLen)) 
    fi 
    i=$((i + 1)) 
    wordLen=$((wordLen + 1)) 
done 
array+=(${str:strP:$wordLen}) 

declare -p array 

方法のより多くの粗種類

#!/bin/bash 

str="LearnABCtoABCSplitABCaABCString" 
delimiter=ABC 
s=$str$delimiter 
array=(); 
while [[ $s ]]; do 
    array+=("${s%%"$delimiter"*}"); 
    s=${s#*"$delimiter"}; 
done; 
declare -p array 

(@gniourf_gniourfのコメントから) - ハァッ... Bash Split String

+0

これは壊れています(文字列にグロブ文字やスペースなどが含まれていると失敗します)。さらに、現代のBashイディオムを使用していないので、コードが本当に奇妙に見えます。 'str =" LearnABCtoABCSplitABCaABCString "delimiter = ABC s = $ str $ delimiter array =();単純なループが必要です。 while [[$ s]];配列+ =( "$ {s %%" $デリミタ "*}"); s = $ {s#* "$区切り文字"};完了しました。宣言-p配列 '。それで全部です。 –

+0

@gniourf_gniourfありがとうございました。私はBash Scriptingを始めました。あなたの提案は、慣用的なアプローチで考えるのに本当に役立ちます。 –

関連する問題