2011-10-09 13 views
0

取り扱い正規表現とファイル:シェル・プログラム・コードについて:私は貝にこの小さなプログラムを書いている

I)私が行う:

if [[ -r $inputfile && -w $outputfileNOM && -w $outputfilePGP ]]; then 
[...] 
else 
    echo "FILE: $inputfile does not exist or does not have read permissions" 
    echo "FILE: $outputfileNOM does not exist or does not have write permissions" 
    echo "FILE: $outputfilePGP does not exist or does not have write permissions" 
fi 

#!/bin/bash 

#*************************************************************** 
# Synopsis: 
# Read from an inputfile each line, which has the following format: 
# 
# llnnn nnnnnnnnnnnnllll STRING lnnnlll n nnnn nnnnnnnnn nnnnnnnnnnnnnnnnnnnn ll ll 
# 
# where: 
# n is a <positive int> 
# l is a <char> (no special chars) 
# the last set of ll ll could be: 
# - NV 
# - PV 
# 
# Ex: 
# AVO01 000060229651AVON FOOD OF ARKHAM C A S060GER 0 1110 000000022 00031433680006534689 NV PV 
# 
# The program should check, for each line of the file, the following: 
# I) If the nnn of character llnnn (beggining the line) is numeric, 
# this is, <int> 
# II) If the character ll ll is NV (just one set of ll) then 
# copy that line in an outputfile, and add one to a counter. 
# III) If the character ll ll is NP (just one set of ll) then 
#  copy that line in an outputfile, and add one to a counter. 
# 
# NOTICE: could be just one ll. Ex: [...] NV [...] 
#         [...] PV [...] 
#   or both Ex: [...] NV PV [...] 
# 
# 
# Execution (after generating the executable): 
# ./ inputfile outputfileNOM outputfilePGP 
#*************************************************************** 


# Check the number of arguments that could be passed. 
if [[ ${#@} != 3 ]]; then 
     echo "Error...must be: myShellprogram <inputfile> <outputfileNOM> <outputfilePGP>\n" 
    exit 
fi 

#Inputfile: is in position 1 on the ARGS 
inputfile=$1 
#OutputfileNOM: is in position 2 on the ARGS 
outputfileNOM=$2 
#OutputfilePGP: is in position 3 on the ARGS 
outputfilePGP=$3 

#Main variables. Change if needed. 
# Flags the could appear in the <inputfile> 
# 
# ATTENTION!!!: notice that there is a white space 
# before the characters, this is important when using 
# the regular expression in the conditional: 
# if [[ $line =~ $NOM ]]; then [...] 
# 
# If the white space is NOT there it would match things like: 
# ABCNV ... which is wrong!! 
NOM=" NV" 
PGP=" PV" 
#Counters of ocurrences 
countNOM=0; 
countPGP=0; 


#Check if the files exists and have the write/read permissions 
if [[ -r $inputfile && -w $outputfileNOM && -w $outputfilePGP ]]; then 
    #Read all the lines of the file. 
    while read -r line 
     do 
      code=${line:3:2} #Store the code (the nnn) of the "llnnn" char set of the inputfile 

      #Check if the code is numeric 
      if [[ $code =~ ^[0-9]+$ ]] ; then 

       #Check if the actual line has the NOM flag 
       if [[ $line =~ $NOM ]]; then 
        echo "$line" >> "$outputfileNOM" 
        ((++countNOM)) 
       fi 

       #Check if the actual line has the PGP flag 
       if [[ $line =~ $PGP ]]; then 
        echo "$line" >> "$outputfilePGP" 
        ((++countPGP)) 
       fi 

      else 
       echo "$code is not numeric" 
       exit 

      fi  

     done < "$inputfile" 

    echo "COUN NON $countNOM"  
    echo "COUN PGP $countPGP" 
else 
    echo "FILE: $inputfile does not exist or does not have read permissions" 
    echo "FILE: $outputfileNOM does not exist or does not have write permissions" 
    echo "FILE: $outputfilePGP does not exist or does not have write permissions" 
fi 

私はいくつかの質問を持っています

私は他のものを印刷したいと思います。したがって、正しいメッセージを印刷してください。例: "$ outputfileNOM"に書き込み権限がない場合は、そのエラーを出力してください。しかし、私がもし/他のたくさん入れたくない、例:

if [[ -r $inputfile ]]; then 
[...] 
if [[-w $outputfileNOM ]] then 
[...] 
else 
    For the READ permission, and the other else for the WRITE 

はそれを行う方法は、ネスティング手法を用いてずにあり、それは読みやすさを維持しています。約

II):私はフラグを使用する場合

if [[ -r $inputfile && -w $outputfileNOM && -w $outputfilePGP ]] 

の代わりに-rまたは-w "-x" OKです。

3)私のコードにATTENTIONラベルがあることに注意してください。私はいくつかの可能性があることに気付いています。例えば、前、後、前、後に空白があります。私は入力ファイルの一貫性を信じていますが、変更された場合、それは爆発します。この場合、私は何ができますか?それを管理するエレガントな方法はありますか? (例外?)

ありがとうございました!

+0

これはshで書かれている特別な理由はありますか? PerlやPythonでもっとクリーンなプログラムを手に入れることができます。 –

+0

@Rafe:はい、私は選択肢がありませんでしたが、シェルに書き込まれる必要があります。 – Kani

+0

BTW - あなたのコードを破棄したバージョンを用意していれば、誤動作を起こすほどのものになるでしょう。私はそれが非常にイライラの記憶をトリップしたこと以外はこれを見ていないだろう。 – dmckee

答えて

0

まあ、助けてくれた人に感謝します。彼らの提案で、私は自分の質問にお答えします:

について:

I)は、このソリューションの利用条件文が、非常にエレガントです:

#File error string 
estr='ERROR: %s files does no exist or does not have %s permissions.\n' 

#Check if the files exists and have the write/read permissions 
[ -r $inputfile ] || { printf "$estr" "<$inputfile>" "read" && exit; } 
[ -w $outputfileNOM ] || { printf "$estr" "<$outputfileNOM>" "write" && exit; } 
[ -w $outputfilePGP ] || { printf "$estr" "<$outputfilePGP>" "write" && exit; } 

お知らせ。終了後に

文字が影響を受けるユーザーのファイルモードビットを選択rwxXst:のchmodのマニュアルから

II)R(読み取り)、書き込み(W)、実行(またはディレクトリを検索() X)...

そしてウィキペディア(ファイルシステム権限)から:

読み取りpermi ssion:ファイルを読み取る機能を許可します。ディレクトリに設定すると、ディレクトリ内のファイル名を読み取ることができます(ただし、内容、ファイルの種類、サイズ、所有権、アクセス許可などの詳細情報は見つかりません)

ファイルを変更する権限を与える書き込み権限。ディレクトリに対して設定されている場合、この権限はディレクトリ内のエントリを変更する機能を許可します。これには、ファイルの作成、ファイルの削除、およびファイルの名前変更が含まれます。

実行権限は、ファイルを実行する権限を与えます。オペレーティングシステムが実行可能にするためには、実行可能バイナリ(コンパイルされたC++プログラムなど)またはシェルスクリプト(たとえばPerlプログラム)に対してこのアクセス許可を設定する必要があります。ディレクトリに対して設定されている場合、このアクセス権は、ファイルまたはサブディレクトリにアクセスするためにツリーを走査する機能を許可しますが、ディレクトリ内のファイルの内容は表示しません。

3)@dmckeeのリンクとカメに感謝します。

# ATTENTION!!!: notice the \< and \> surrounding 
# the characters, this is important when using 
# the regular expression in the conditional: 
# if [[ $line =~ $NOM ]]; then [...] 
# 
# If those characters are NOT there it would match things like: 
# ABCNV ... which is wrong!! 
# They (the \< and \>) indicate that the 'NV' can't be 
# contained in another word. 
NOM='\<NV\>' 
PGP='\<PV\>' 
0

私は以前に=~オペレータによって噛まれてきました。私は、引数を引用するように指示したい原則として

(すなわち... =~ "$NOM")、しかし=~ ""starting with bash 3.2 there is a special behavior。かなり長ったらしいあるリンクは、()言う:

oは他のパターンマッチング事業者と同様に、 力文字列マッチングになりました[[コマンドの=〜(正規表現)オペレータへの文字列引数を引用します。

E14)なぜ動作を停止する 条件演算子(=〜)原因の正規表現のマッチングに一致する正規表現にパターン引数を引用していますか?

bash-3.2より前のbashのバージョンでは、正規の 式の引き数を[[コマンドの=〜演算子]に指定するという効果が指定されていませんでした。 二重引用符で囲まれた語の展開で行われた バックスラッシュ処理を妨げ、==シェルパターンマッチング演算子が処理された方法と矛盾する 特殊文字を引用符で囲むためには、パターン引数を二重引用符で囲む必要がありました 引用符で囲まれた文字。

bash-3では。2の場合、シェルは単一の の文字を内部的に引用するように変更され、=〜演算子の二重引用符で囲まれた文字列引数は、 正規表現処理に特有の文字の特別な意味を抑制する。 (.', ['、\',), *「+',?」、{', |」、^', and $ 『)と力 彼らは文字通り一致する。これは、そのパターン引数の部分を引用したか、` ==』パターン マッチング演算子の扱いと一致している

引用符で囲まれた文字列引数の扱いが変更されたため、いくつかの問題 が発生しました。パターン引数 の空白のoblemと、bash-3.1とbash-3.2の間の引用文字列の扱いが異なります。 両方の問題は、シェル変数を使用してパターンを保持することで解決できます。 [[コマンド]のすべての オペランドでシェル変数を展開するときにワードスプリットは実行されないので、変数を割り当てる際にユーザは のパターンを引用できるようになります。最初の問題は、バックスラッシュ またはパターンの空白をエスケープするための他の引用メカニズムを使用して解決できます。

NOM="[ ]NV"の行に沿って何かが考えられます。 (私はこれをテストしていないことに注意してください)

+0

チップをありがとう!私が[I]、[II]、[III]の答えを得ることができたら、待ってください! – Kani

関連する問題