Unix 쉘 스크립트 파일의 첫 번째 줄에 있는 일치하는 문자열을 기반으로 텍스트 파일 이름 바꾸기

Unix 쉘 스크립트 파일의 첫 번째 줄에 있는 일치하는 문자열을 기반으로 텍스트 파일 이름 바꾸기

저는 Unix 스크립팅을 처음 접했습니다.

첫 번째 줄(예: 로 시작하는 줄)의 일치하는 문자열을 기반으로 HDR파일 이름을 바꾸고 싶습니다.

File.txt다음과 같은 텍스트 파일( )이 있습니다 .

HDR##############################1234###
########################################
########################################

아래는 내 코드입니다. 패턴으로 시작하고 HDR패턴이 있는 파일의 첫 번째 줄에 대해 내 코드에서 더 구체적으로 확인하려면 어떻게 해야 합니까 1234?5678

if grep -o "1234" File.txt

then mv File.txt Pattern1.txt

echo "File with pattern1 received..."

elif grep -o "5678" File.txt

then mv File.txt Pattern2.txt

echo "File with pattern2 received..."

else

echo "File have no matching pattern..."

fi

답변1

줄을 읽으려면 "read"를 사용하고, 무엇을 할지 결정하려면 "case"를 사용하세요.

{
  IFS= read -r Firstline
  case "$Firstline" in
     ("HDR"*"1234"*) mv File.txt Pattern1.txt
                echo "File with pattern1 received..." ;;
     ("HDR"*"5678"*) mv File.txt Pattern2.txt
                echo "File with pattern2 received..." ;;
     (*)        echo "Nothing matched" ;;
  esac
} < File.txt

답변2

-n( --line-number) 옵션을 사용하여 grep선을 식별한 다음 case패턴을 일치시킵니다.

Tmp=$(grep -n "HDR.*[0-9]\{4\}" File.txt)
if [ "${Tmp%:*}" -eq 1 ]
  then  case "${Tmp#*:}" in
          HDR*1234*)    NewName="Pattern1";;
          HDR*5678*)    NewName="Pattern2";;
        esac
        if [ "$NewName" ]
          then  mv -- File.txt "$NewName".txt
                echo "File with $NewName received..."
          else  echo "File doesn't have a matching pattern..."
        fi
  else  echo "File doesn't have a pattern in line 1"
fi

답변3

Perl rename유틸리티를 사용하십시오.

file-rename참고: Perl 이름 바꾸기는 , perl-rename, 또는 이라고도 합니다 prename. 기능과 명령줄 옵션이 완전히 다르고 호환되지 않는 rename유틸리티와 혼동 하지 마십시오.util-linux

$ rename -n ' BEGIN {
      # This block runs only once when the script starts, there's no need
      # to redefine these vars on every pass through the loop.  File::Rename
      # scripts run with `use strict vars`, so we need to be careful about
      # variable scope.  See `perldoc -f our`
      our %patterns=(1234 => "Pattern1.txt", 5678 => "Pattern2.txt");
      our $re = "^HDR#+(" . join("|",keys %patterns) . ")#+$";
    };
    
    # The remainder of the script runs once for every filename
    our (%patterns, $re); # these vars are in File::Rename lexical scope

    open(my $fh,"<",$_); my $line=<$fh>; close($fh);
    if ($line =~ /$re/) { $_ = $patterns{$1} }' File*
rename(File1.txt, Pattern1.txt)
rename(File2.txt, Pattern2.txt)

(이것은 두 개의 텍스트 파일(샘플 데이터의 복사본)에서 실행되었습니다. File1.txt에는 File.txt 예제와 정확히 동일한 1234가 포함되어 있는 반면 File2.txt는 5678을 포함하도록 편집되었습니다.)

-n옵션을 사용하면 시험적으로 실행되므로 실제로 파일 이름을 바꾸지 않고 수행할 작업만 표시됩니다. 요구사항을 충족하는 것으로 확인되면 삭제 -n하거나 로 대체하여 자세한 출력을 얻으세요.-v

이 이름 바꾸기 스크립트는 해시를 사용하여 %patterns검색할 패턴과 이름을 바꿀 패턴이 포함된 파일의 파일 이름을 저장합니다. 변수의 해시 키를 기반으로 정규식을 구성합니다 $re.

그런 다음 현재 파일 이름을 열고 첫 번째 줄을 읽습니다. 첫 번째 줄이 패턴 중 하나와 일치하면 해당 파일 이름으로 이름이 변경됩니다.

이러한 해시를 사용하면 스크립트를 더 많거나 다른 패턴으로 쉽게 확장할 수 있습니다. 해시 %patterns(및 그 안의 합계 )를 ^HDR#+(제외하고는 아무것도 하드코딩되지 않습니다 .)#+$$re

-f참고: 또는 옵션을 사용하여 --force강제로 이름을 바꾸지 않는 한 이름을 바꾸면 기존 파일을 덮어쓰지 않습니다 . 이는 기존 파일과 방금 이름이 변경된 파일 모두에 적용됩니다. 여러 파일에 동일한 패턴이 포함되어 있으면 첫 번째 파일의 이름만 변경됩니다. -f물론 를 사용하면 기존/이전에 이름이 바뀐 파일을 덮어쓰게 됩니다. 더 나은 대안은 카운터 변수(예: 파일 이름이나 패턴을 키로 사용하는 해시)를 사용하여 파일 이름을 , Pattern1.txt.001Pattern1.txt.002으로 바꾸는 것입니다.

또는 다음 fileparse()기능을 사용하십시오파일::기본 이름모듈이 도착했습니다 Pattern1-001.txt. Pattern1-002.txt잠시만 기다려주세요.

예를 들어

$ rename -n 'BEGIN {
    use File::Basename;
    our %seen=();
    our %patterns=(1234 => "Pattern1.txt", 5678 => "Pattern2.txt");
    our $re = "^HDR#*(" . join("|",keys %patterns) . ")"
  };

  our(%seen, %patterns, $re);
  open(my $fh,"<",$_); my $line=<$fh>; close($fh);
  if ($line =~ /$re/) {
    my($name,$path,$suffix) = fileparse($patterns{$1}, qr/\.[^.]*$/);
    $_ = sprintf "%s-%03i%s", $name, ++$seen{$1}, $suffix
  }' File*
rename(File1.txt, Pattern1-001.txt)
rename(File2.txt, Pattern2-001.txt)
rename(File3.txt, Pattern1-002.txt)

관련 정보