2011-10-09 5 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

이가 쉬에 기록 된 특별한 이유가 있나요? 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 : 파일을 읽을 수있는 권한을 부여합니다. 디렉터리에 대해 설정되면이 사용 권한은 디렉터리의 파일 이름을 읽을 수있는 권한을 부여합니다 (내용, 파일 형식, 크기, 소유권, 사용 권한 등과 같은 추가 정보는 찾을 수 없음)

파일을 수정할 수있는 권한을 부여하는 쓰기 권한. 디렉토리에 대해 설정되면이 사용 권한은 디렉토리의 항목을 수정할 수있는 권한을 부여합니다. 여기에는 파일 작성, 파일 h 제 및 파일 이름 변경이 포함됩니다.

파일을 실행할 수있는 권한을 부여하는 실행 권한. 이 사용 권한은 실행 바이너리 (예 : 컴파일 된 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. 오히려 말의 인 링크()는 말한다 :

오 다른 패턴 일치 연산자로, 힘 문자열 매칭 이제 [[명령의 = ~ (정규 표현식) 연산자로 문자열 인수를 인용.

E14)은 왜 조건 연산자 (작동이 중지 = ~) 원인 정규 표현식 매칭을 일치하는 정규 표현식의 패턴 인수에 인용 부호를합니까?

bash-3.2 이전의 bash 버전에서는 정규식 인수를 [[명령의 = ~ 연산자]로 지정하는 효과가 지정되지 않았습니다. 패턴 인수를 큰 따옴표로 묶을 때 백 슬래시가 특수 패턴 문자를 인용해야하며 큰 따옴표 단어 확장으로 수행되는 백 슬래시 처리를 방해했으며 은 == 쉘 패턴 일치 연산자가 처리 된 방법과 일치하지 않음 따옴표 붙은 문자.

bash-3.2, 쉘은 '(\','정규 표현식 처리 특수 문자의 특별한 의미 (.', [을 억제 = ~ 연산자에 단일 및 이중 인용 부호가있는 문자열 인수에서 내부적으로 인용 문자로 변경되었습니다, ), * ', +',?'{', |. 그들이 문자 그대로 일치하는 '^', and $')을하고 힘 이는 패턴 인수의`== '패턴 일치 연산자 취급 인용 방법 부분과 일치

.

따옴표로 묶인 문자열 인수의 처리가 변경되었으므로 몇 가지 문제가 발생했습니다. 패턴 인자 에 공백이있는 oblem과 bash-3.1과 bash-3.2 사이에서 따옴표로 묶인 문자열을 다르게 처리합니다. 두 변수 모두 쉘 변수를 사용하여 패턴을 유지하면 문제가 해결 될 수 있습니다. [[명령의 모든 피연산자에서 쉘 변수를 확장 할 때 단어 분리가 수행되지 않으므로 사용자가 변수를 지정할 때 을 원하는대로 패턴을 인용 할 수 있으므로 값을 공백이 포함될 수있는 단일 문자열로 확장하십시오. 첫 번째 문제는 백 슬래시 또는 다른 인용 메커니즘을 사용하여 패턴의 공백을 이스케이프 처리하여 해결할 수 있습니다.

NOM="[ ]NV" 줄을 따라 생각해보십시오. (나는 이것을 테스트하지 않았다.)

+0

팁 주셔서 감사합니다! 내가 [I], [II], [III]에 대한 답을 얻을 수 있다면 기다리고 !! – Kani

관련 문제