1

sedを使用してパターンに基づいて文字列の行を分割するシェルスクリプトを書いています。

    #pattern 'string1','string2','string3'

    cat $FILENAME | while read LINE
    do

    firstPart=$(echo "$LINE" | sed -r "s/'(.*)','(.*)','(.*)'/\1/" )
    secondPart=$(echo "$LINE" | sed -r "s/'(.*)','(.*)','(.*)'/\2/" )
    thirdPart=$(echo "$LINE" | sed -r "s/'(.*)','(.*)','(.*)'/\3/" )

    done

個別のエコーを使用して印刷することはできますが、以下に示すように単一のエコーに入れると

    #if LINE from FILE is '123','abc','hello'

    echo "$firstPart $secondPart"
    #this prints " abc" instead of "123 abc"

    #try appending a string on echo
    echo "$firstPart -"
    #this prints " -3" instead of "123 -"

コード内の定数文字列でsedを使用しようとすると、echoは問題ないようです。

    #Correct Echo
    SOMESTRING='123','abc','hello'

    firstPart=$(echo "$SOMESTRING" | sed -r "s/'(.*)','(.*)','(.*)'/\1/" )
    secondPart=$(echo "$SOMESTRING" | sed -r "s/'(.*)','(.*)','(.*)'/\2/" )
    thirdPart=$(echo "$SOMESTRING" | sed -r "s/'(.*)','(.*)','(.*)'/\3/" )

    echo "$firstPart $secondPart"
    #this prints "123 abc"

入力がFILEからのLINEである場合、sedの正しい動作ですか?LINEがコードに含まれて宣言されているかのように動作させるにはどうすればよいですか(2番目の例のように)。

4

4 に答える 4

2

\r文字列に改行(時々書かれる)が埋め込まれているように見えます。したがってecho "$firstPart -"、firstPart="123\r" を実行すると、次の 2 行が出力されます。

123
 -

...2番目の「行」が最初の行の上に印刷されます(そして上書きされます)。私の推測では、あなたは DOS スタイルの行末を使用するテキスト エディターでスクリプトを編集したと思います (つまり、各行は復帰と改行で終わります) が、シェルは UNIX スタイルの行末 (改行のみ) を想定し、コマンドの一部としてのキャリッジ リターン (たとえばfirstPart=$(echo "$SOMESTRING" | sed -r "s/'(.*)','(.*)','(.*)'/\1/" )\r\rfirstPart.

これが問題である場合は、スクリプトで dos2unix を実行すると修正されます (その後、DOS スタイルの行末を使用しないエディターに切り替えます)。

于 2012-12-20T12:22:24.820 に答える
0

SOMESTRING='123','abc','hello'bashと言うと、一重引用符が取り除かれます。

$ echo "$SOMESTRING"
123,abc,hello

それらを保持したい場合は、 と言う必要がありますSOMESTRING="'123','abc','hello'"

これは、sed パターンが機能しないことを意味します。たとえばfirstPart、空の文字列に設定されています。sed パターンから一重引用符を削除すると機能します。

IFSただし、区切られた単純な入力を分割するために使用することをお勧めします。

echo "'123','abc','hello'" | while IFS=, read a b c; do
  echo $a
  echo $b
  echo $c
done

または簡単に:

while IFS=, read a b c; do echo -e "$a\n$b\n$c"; done <<< "'123','abc','hello'" 

出力:

'123'
'abc'
'hello'
于 2012-12-20T10:48:35.323 に答える
0

私は専門家ではありませんが、"while" スクリプトをパイプ処理する場合、while 内で使用される変数はメイン スクリプトでは使用できないと言えます。

例: while ループ内で echo ステートメントを使用すると、SED による解析が適切であることを示します。

または、次の構文を使用して、これらの変数をメイン スクリプトで公開することもできます。

while read LINE
do

firstPart=$(echo "$LINE" | sed -r "s/'(.*)','(.*)','(.*)'/\1/" )
secondPart=$(echo "$LINE" | sed -r "s/'(.*)','(.*)','(.*)'/\2/" )
thirdPart=$(echo "$LINE" | sed -r "s/'(.*)','(.*)','(.*)'/\3/" )
done < $FILENAME
于 2012-12-20T11:04:42.637 に答える
0
SOMESTRING='123','abc','hello'

firstPart=$(echo "$SOMESTRING" | sed "s/\([^,]*\),\([^,]*\),\([^,]*\)/\1/" )
secondPart=$(echo "$SOMESTRING" | sed "s/\([^,]*\),\([^,]*\),\([^,]*\)/\2/" )
thirdPart=$(echo "$SOMESTRING" | sed "s/\([^,]*\),\([^,]*\),\([^,]*\)/\3/" )
于 2014-05-08T05:01:07.390 に答える