12

Unix のテキスト ファイルからレコードを取得する必要があります。区切り文字は複数のブランクです。例えば:

2U2133   1239  
1290fsdsf   3234

これから、抽出する必要があります

1239  
3234

すべてのレコードの区切り文字は常に 3 つの空白になります。

これを UNIX スクリプト (.scr) で実行し、出力を別のファイルに書き込むか、do-while ループへの入力として使用する必要があります。私は以下を試しました:

while read readline  
do  
        read_int=`echo "$readline"`  
        cnt_exc=`grep "$read_int" ${Directory path}/file1.txt| wc -l`  
if [ $cnt_exc -gt 0 ]  
then  
  int_1=0  
else  
  int_2=0  
fi  
done < awk -F'  ' '{ print $2 }' ${Directoty path}/test_file.txt  

test_file.txt は入力ファイルで、file1.txt はルックアップ ファイルです。しかし、上記の方法は機能せず、 awk -F の近くで構文エラーが発生します

出力をファイルに書き込もうとしました。以下はコマンドラインで機能しました:

more test_file.txt | awk -F'   ' '{ print $2 }' > output.txt

これは機能しており、コマンドラインでレコードを output.txt に書き込んでいます。ただし、同じコマンドは unix スクリプトでは機能しません (.scr ファイルです)。

どこが間違っているのか、どうすれば解決できるのか教えてください。

ありがとう、
ヴィサフ

4

8 に答える 8

27

複数の区切り文字を 1 つだけに置き換える作業は、次のように残されていtrます。

cat <file_name> | tr -s ' ' | cut -d ' ' -f 2

tr文字を変換または削除し、適切に動作するようにデータを準備するのに最適cutです。

マニュアルには次のように記載されています。

-s, --squeeze-repeats
          replace each sequence  of  a  repeated  character  that  is
          listed  in the last specified SET, with a single occurrence
          of that character
于 2013-06-10T09:07:58.733 に答える
12

マシンのバージョンまたは実装によって異なりcutます。一部のバージョンでは、通常-i、「空白フィールドを無視する」ことを意味するオプション、または同等に、フィールド間に複数のセパレータを許可するオプションがサポートされています。それがサポートされている場合は、次を使用します。

cut -i -d' ' -f 2 data.file

そうでない場合 (そしてそれは普遍的ではありません — GNU にも MacOS X にもオプションがないため、普及していない可能性さえあります)、使用するawk方が優れており、より移植性があります。

awkただし、の出力をループにパイプする必要があります。

awk -F' ' '{print $2}' ${Directory_path}/test_file.txt |
while read readline  
do  
    read_int=`echo "$readline"`  
    cnt_exc=`grep "$read_int" ${Directory_path}/file1.txt| wc -l`  
    if [ $cnt_exc -gt 0 ]  
    then int_1=0  
    else int_2=0
    fi  
done

唯一の残りの問題は、whileループがサブシェルにあるかどうか、したがってメインのシェル スクリプト変数を変更せず、それらの変数の独自のコピーだけを変更するかどうかです。

bash では、プロセス置換を使用できます。

while read readline  
do  
    read_int=`echo "$readline"`  
    cnt_exc=`grep "$read_int" ${Directory_path}/file1.txt| wc -l`  
    if [ $cnt_exc -gt 0 ]  
    then int_1=0  
    else int_2=0
    fi  
done < <(awk -F' ' '{print $2}' ${Directory_path}/test_file.txt)

これによりwhile、現在のシェルにループが残されますが、コマンドの出力がファイルからのように表示されるように調整されます。

の空白${Directory path}は、通常は合法ではありません — それが私が見逃した別の Bash 機能でない限り。また、タイプミス ( Directoty) が 1 か所ありました。

于 2010-12-06T15:14:10.480 に答える
3

<同じことを行う他の方法は別として、プログラムのエラーは次のとおりです。別のプログラムの出力を( ) からリダイレクトすることはできません。スクリプトを逆にして、次のようなパイプを使用します。

awk -F'   ' '{ print $2 }' ${Directory path}/test_file.txt | while read readline

さらに、変数名として「readline」を使用すると、問題が発生する場合と発生しない場合があります。

于 2010-12-06T15:09:50.973 に答える
2

この特定のケースでは、次の行を使用できます

sed 's/   /\t/g' <file_name> | cut -f 2

2 番目の列を取得します。

于 2012-01-18T22:18:36.767 に答える
1

bash では、次のようなものから開始できます。

for n in `${Directoty path}/test_file.txt | cut -d " " -f 4`
{
    grep -c $n ${Directory path}/file*.txt
}
于 2010-12-06T14:44:26.857 に答える
1

これはコメントである必要がありましたが、まだコメントできないため、ここに追加します。これは優れた回答からのものです: https://stackoverflow.com/a/4483833/3138875

tr -s ' ' <text.txt | cut -d ' ' -f4

tr -s '<character>'の複数の繰り返しインスタンス<character>を 1 つに絞り込みます。

于 2019-03-26T19:07:20.900 に答える
0

「Directo* t *y path」(スクリプトの最後の行) のタイプミスのため、スクリプトでは機能しません。

于 2010-12-06T14:59:33.530 に答える