2016-05-19 9 views
2

私はこのような行を含むファイルを持っている:Bashではファイルを文字列と複数の空白でどのように扱うのですか?

私は列の一部で、ファイルの上に行くと、それをソートする必要がある
street "City Name" 5 7500 30.3.2016 
"Street Name" city 4 1000 15.01.2015 
<street name> <city name> <num of room> <price> <date> 

- などの名前価格日付などの

私は白とこだわっています(各パラメータの間に複数の空白があります)と文字列の間(1語または2以上)と単語の先頭に(そして私はsedを使用できません)

street "City Name" 5 7500 3.30.2016 
"Street Name" city 4 1000 01.15.2015 
+2

これは興味深い問題になるのは空白ではなく*引用符*です。 –

+0

...引用符で囲まれていてもスペースを使用して、あなたが望む*出力フォーマットは、現在のフォーマットよりも標準的なUNIXツールで簡単にソートすることはできません。タブまたはその他の区切り記号がジョブの正しいツールです。 –

+1

@CharlesDuffy:日付がまだd-m-yからm-d-y形式に変換されていることは誰も気づいていません。少なくとも、私は物事を編集する前に2番目でした。最初のものはより微妙に変形した( '30.3.2016'から' 3.28.2016'に)。私は数字を一致させました - しかし、OPはこの変換が質問の一部であるかどうかを明確にすべきです。 –

答えて

1

あなたは

(スクイズを意味する) -sフラグで trを使用することができます。

誰も私のような線で残されますので、複数の空白を失うことを私にソリューションを提供することができます

echo " a sentence  with lots of spaces" | tr -s " " 

cut

echo " a sentence  with lots of spaces" | tr -s " " | cut -d ' ' -f2- 
てあなたが最初のスペースを削除したい場合は、単にパイプを

EDITは:

awk -F \" -v OFS=\" '{for (i=1; i<=NF; i=i+2) while (sub(/ /," ",$i)) ; print}' afile1 

目標は残すことである:チャールズ・ダフィーがあなたの代わりにsedを使用することができます示唆したように、ケースであなたを保護するためにこれに試してみて何の先頭にスペース

echo " a sentence  with lots of spaces" | tr -s " " | sed -re 's/^ +//' 
+0

なぜ-f1-の代わりに-f2-?私たちは最初の列からそれを望んでいないのですか? –

+1

最初の列は1つの空白です –

+0

私は 'sed -re 's/^ + //''を 'cut'よりも先に提案しています - あなたの入力が*持っていなかったら何も壊れません先頭のスペース。 –

1

ありません2 "に囲まれた文字列は、2 "以外の複数のスペースを1つに置き換えます。

-v OFS=\"は、printを使用すると、出力のフィールドセパレータとして"を定義します。

-F \"は、入力行の読み込みのフィールドセパレータとして"を定義します。変数は、$1$2などの変数に格納されているいくつかの要素で、"に従って分割されます。

したがって、奇数フィールド($1,$3など)は2 "の外側にあります。

NFは、分割後の現在の行にある要素の数です。

forステートメントは奇数フィールドのみでループしています。 gsubは、奇数フィールドの複数のスペースをすべて1つのスペースに置き換えます。

テスト:

$ awk -F \" -v OFS=\" '{for (i=1; i<=NF; i=i+2) gsub(/ */," ",$i) ; print}' afile 
street "City Name" 5 7500 30.3.2016 
"Street Name" city 4 1000 15.01.2015 
<street name> <city name> <num of room> <price> <date> 
2

以下はsortまたは他の標準的なツールは自明、それを扱うことができるタブ区切り形式、にあなたのファイルを変換します:xargsは引用符を解析するので、これは動作します

while read -r line; do 
    printf '%s\n' "$line" | xargs printf '%s\t' 
    echo 
done 

各行を個々の要素に分割し、次に各要素をprintf '%s\t'に渡します。この要素は、それらの要素をタブで表示します。 echoは出力行の間に改行を追加します。

出力は、次のようなものに供給することができる:上、その後、(あなたの例では都市、)2番目のキーの最初の、タブ区切りの列をソートします

sort -t $'\t' -k2,2 -k1,1 

...最初のもの(あなたの例では通りの名前)。 、LANG=C sort -s -t$'\t' -k2,2 -k1,1 | expand -t16で、上記通じ

"Street A" "City A" 1 
"Street B" "City B" 2 
"A Street" "City A" 3 
"B Street" "City B" 4 
"Street A" "A City" 5 
"Street B" "B City" 6 
Street City 7 

ラン - ので、市内で最初の並べ替え:


のは、当初の提案の場合と比べてより明確な行動を行います以下の入力ファイルを、見てみましょうストリートによって第一ソートするLANG=C sort -s -t$'\t' -k1,1 -k2,2 | expand -t16を使用し、一方

Street A  A City   5 
Street B  B City   6 
Street   City   7 
A Street  City A   3 
Street A  City A   1 
B Street  City B   4 
Street B  City B   2 

:以下のように出力される - は、ストリートによって、次いで16空間タブストップで印刷その後、市が(16-スペースタブで印刷)し、次の取得:

A Street  City A   3 
B Street  City B   4 
Street   City   7 
Street A  A City   5 
Street A  City A   1 
Street B  B City   6 
Street B  City B   2 

あなたが戻って引用された形式にタブ区切り形式から行きたい場合は、これが実現可能ですあまりに:

#!/bin/bash 
#  ^^^^- Important, not /bin/sh 

while IFS=$'\t' read -r -a cols; do 
    for col in "${cols[@]}"; do 
    if [[ $col = *[[:space:]]* ]]; then 
     printf '"%s" ' "$col" 
    else 
     printf '%s ' "$col" 
    fi 
    done 
    printf '\n' 
done 

(タブ区切り形式に変換するために)あなたの元の入力を取り、最初のスクリプトを通してそれを実行し、その後、sort -t$'\t' -k1,1 -k2,2(そのフォームでソートする)は、この2番目のスクリプトは、(空白に戻って変換します区切り文字は引用符で囲みます)、次のようになります。

"A Street" "City A" 3 
"B Street" "City B" 4 
Street City 7 
"Street A" "A City" 5 
"Street A" "City A" 1 
"Street B" "B City" 6 
"Street B" "City B" 2 
関連する問題