2011-10-10 13 views
36

カンマでテキストを分割したい,スペースなしfor foo in listにします。私はいくつかの単語に分割するには、次のコードを使用カンマでリストを分割する方法

Hello,World,Questions,Answers,bash shell,script 
... 

for word in $(cat CSV_File | sed -n 1'p' | tr ',' '\n') 
do echo $word 
done 

それは印刷されます。

Hello 
World 
Questions 
Answers 
bash 
shell 
script 

しかし、私が、私はCSVは、その中に次のテキストでCSV_Fileファイルがあるとしスペースではなくコンマで区切りたい:

Hello 
World 
Questions 
Answers 
bash shell 
script 

これをどのようにしてbashで実現できますか?

+0

なぜawkを使用しないのですか? –

+2

@Carl「awk」の使用例を教えてください。 –

答えて

38

単語を解析するためにサブシェル置換を使用すると、スペースを一緒に入れる作業がすべて元に戻されます。

ではなく、試してみてください。また、並列性を高める

cat CSV_file | sed -n 1'p' | tr ',' '\n' | while read word; do 
    echo $word 
done 

を。あなたの質問にあるようにサブシェルを使うと、サブシェルのプロセス全体が終了してから、回答を繰り返し処理することができます。サブシェルにパイプを張って(私の答えのように)、それらを並行して動作させることができます。もちろん、ファイル内にたくさんの行がある場合にのみ重要です。

+1

そうです、これは私が提案した方法よりも良い方法です。 +1のl33t bashスキルmkj :) – chown

+0

+1ありがとうmkj。これは私が探しているものです –

+1

whileループは必要ありません。 –

8
kent$ echo "Hello,World,Questions,Answers,bash shell,script"|awk -F, '{for (i=1;i<=NF;i++)print $i}' 
Hello 
World 
Questions 
Answers 
bash shell 
script 
+0

+1ありがとうございました。私は後でこの解決策を試してみる –

+1

私は 'echo $ word'は$ wordで行う必要のある実際のものではないと仮定しています。この場合、あなたのawkの公開は元の質問のsedとtrを行う別の方法です。私は、Eng.Fouadがスペースを使って他の何かをするシェル変数に値することを望んでいると思います。 – mkj

+0

@mkjこの解決策は、シェル変数として使用する場合はOKです。例: 'FOO =" Hello、World、Questions、Answers、bash shell、script "; BOO = $(エコー$ FOO | awk -F、 '{(i = 1; i <= NF; i ++)print $ i}'); $ BOOのBのために;エコー "<$B>"; done' –

45

IFSを設定します。

[email protected]:~$ IFS=',' ;for i in `echo "Hello,World,Questions,Answers,bash shell,script"`; do echo $i; done 
Hello 
World 
Questions 
Answers 
bash shell 
script 
[email protected]:~$ 
+0

Nice!私はIFS env変数について忘れてしまった! – chown

+1

最もクリーンで組み込みのソリューションです。これが答えになるはずです。 – Marcos

+0

これをスクリプトで使用するには、IFS変数を以前の値に復元する必要があります。 Andrew Newdigateの答えを見てください。 – clime

5

読む:http://linuxmanpages.com/man1/sh.1.php & http://www.gnu.org/s/hello/manual/autoconf/Special-Shell-Variables.html

IFSザ・内部フィールド区切り拡張後に行を分割する単語分割 のために使用されていますread 組み込みコマンドを含む単語。デフォルト値は `` ''です。

IFSは、シェルスクリプトのコンテキスト内で変更されないようにするため、シェルスクリプトのコンテキスト内で変更されませんが、EXPORTしない限り変更されません。また、IFSはあなたの環境からまったく継承されないだろうことを覚えておいてください。IFSに関する理由と詳細については、このgnuの記事を参照してください。あなたはこのように書かれたコードだ

IFS="," 
for word in $(cat tmptest | sed -n 1'p' | tr ',' '\n'); do echo $word; done; 

が動作するはずですが、私は、コマンドライン上でそれをテストしました。

私は標準的な方法があると思い
sh-3.2#IFS="," 
sh-3.2#for word in $(cat tmptest | sed -n 1'p' | tr ',' '\n'); do echo $word; done; 
World 
Questions 
Answers 
bash shell 
script 
16

while IFS=, read field1 field2 field3 field4 field5 field6; do 
    do stuff 
done < CSV.file 

あなたが知っていないか、そこにどのように多くの分野を気にしない場合:

IFS=, 
while read line; do 
    # split into an array 
    field=($line) 
    for word in "${field[@]}"; do echo "$word"; done 

    # or use the positional parameters 
    set -- $line 
    for word in "[email protected]"; do echo "$word"; done 

done < CSV.file 
+0

名前で特定のフィールドを参照できるようにすると非常に便利です – HXCaine

+0

@ glenn-jackmanあなたは正しいです、正規のUNIXはあなたの最初の方法を使用します。 2つ目は、bashまたはzshの最新の実装でのみ動作します。 –

+1

bashの 'read'コマンドには、行内の単語を配列に読み込むための' -a'オプションがあります: 'read -a words; "$ {words [@]}" ... " –

5

はbashの関数を作成します。

split_on_commas() { 
    local IFS=, 
    local WORD_LIST=($1) 
    for word in "${WORD_LIST[@]}"; do 
    echo "$word" 
    done 
} 

split_on_commas "this,is a,list" | while read item; do 
    # Custom logic goes here 
    echo Item: ${item} 
done 

...これは、

Item: this 
Item: is a 
Item: list 

(注、この答えはいくつかのフィードバックに基づいて更新されている)を使用でき

+1

これは奇妙な副作用があります。http://pastebin.com/gNmkzPqj – Val

+0

奇妙です。どんなアイディアが*なぜ*起こっているのですか? –

+0

ここで副作用が説明されています。http://superuser.com/questions/781766/ifs-separated-items-in-loop – Val

0

:出力をngの

cat f.csv | sed 's/,/ /g' | awk '{print $1 "/" $4}' 

または

echo "Hello,World,Questions,Answers,bash shell,script" | sed 's/,/ /g' | awk '{print $1 "/" $4}' 

これは一部であり、コンマをスペースで置き換えるもの

sed 's/,/ /g' 
関連する問題