Bash 문은 무엇을 합니까?

Bash 문은 무엇을 합니까?

다음 진술이 무엇을 하는지 나에게 설명해 주실 수 있나요?

grep `date +%Y-%m-%d --date='1 day ago'` /path/to/file/FILE_PREFIX_\`date +%Y%m%d --date='1 day ago'`.dsv | grep -v 'ERROR' | cut -d "|" -f 2 | sed 's/^0/27/'

답변1

다음 파일이 있다고 가정해 보겠습니다.

$ cat path/to/file/FILE_PREFIX_20150730.dsv
2015-07-29|0100
2015-07-30|0200
2015-07-30|0300
2015-07-31|0400

이제 (약간 고정된) 명령이 수행하는 작업을 살펴보세요.

$ grep `date +%Y-%m-%d --date='1 day ago'` path/to/file/FILE_PREFIX_`date +%Y%m%d --date='1 day ago'`.dsv  | grep -v 'ERROR' | cut -d "|" -f 2 | sed 's/^0/27/'
27200
27300

간단히 말해서 이름이 어제 날짜를 기반으로 하는 파일을 살펴보고 path/to/file/FILE_PREFIX_20150730.dsv해당 파일에서 형식으로 어제 날짜를 언급하는 모든 줄을 찾습니다 2015-07-30. 그런 다음 문자도 포함된 모든 줄을 제거합니다 ERROR. 나머지 줄은 문자를 기준으로 필드로 구분됩니다 |. 행의 두 번째 필드를 추출합니다. 두 번째 필드가 0으로 시작하면 0이 대체됩니다 27.

답변2

우선, 당신이 제공하는 것은 진술이 아닙니다. 이것은 다음과 같이 연결된 일련의 명령입니다.관로그리고명령 대체.

grep `date +%Y-%m-%d --date='1 day ago'` /path/to/file/FILE_PREFIX_\`date +%Y%m%d --date='1 day ago'`.dsv | grep -v 'ERROR' | cut -d "|" -f 2 | sed 's/^0/27/'

하나씩 분해해 보겠습니다.

명령 대체

  • date +%Y-%m-%d --date='1 day ago'두 번 발생하며 어제 날짜를 형식 YYYY-mm-dd(예: 2015-07-31) 으로 제공합니다.
    • 두 번째 호출(pathname의 호출)은 형식을 다음과 같이 조정합니다.YYYYmmdd
    • 그것을 만들기 위해 백틱에 넣어명령 대체. 이는 $(date +%Y-%m-%d --date='1 day ago')중첩을 허용하고 이스케이프 측면에서 덜 번거로운 후자(및 최신) 형식을 입력하여 얻는 것과 동일한 효과 입니다 .

효과명령 대체명령줄에서 다음과 같은 것을 할당합니다.

YESTERDAY1=$(date +%Y-%m-%d --date='1 day ago')
YESTERDAY2=$(date +%Y%m%d --date='1 day ago')

그런 다음 명령줄을 다음과 같이 다시 작성하세요.

grep $YESTERDAY1 /path/to/file/FILE_PREFIX_$YESTERDAY2.dsv | grep -v 'ERROR' | cut -d "|" -f 2 | sed 's/^0/27/'

파이프로 연결된 개별 구성요소

  • grep $YESTERDAY1 /path/to/file/FILE_PREFIX_$YESTERDAY2.dsvgrep은 파일에서 어제 날짜 값을 찾아서 /path/to/file/FILE_PREFIX_$YESTERDAY2.dsv출력합니다 stdout(참조:표준 스트림)
  • grep -v 'ERROR'모든 것을 grep다른ERROR입력에 대해 이 작업을 수행 stdin하고 에도 씁니다 stdout.
  • cut -d "|" -f 2입력 라인( stdin)이 파이프 문자로 구분된다고 가정하고( -d "|"여기서 파이프 문자가 문자열에 어떻게 나타나는지 확인하십시오!) 두 번째 필드( -f 2)를 선택하여 작성하십시오 stdout.
  • sed 's/^0/27/'( )(원래 입력의 두 번째 필드를 기억) s/.../.../에서 0으로 시작하는 모든 문자열을 27로 바꾸고 작성합니다.stdin^stdout

관로

이제 문자열 외부에 나타나는 파이프 문자, 즉 단일 문자를 제외한 모든 문자는 이전 명령을 cut -d "|" -f 2다음 명령에 연결합니다.stdoutstdin

이렇게 하면 첫 번째 읽기 파일의 출력이 grep두 번째 읽기 파일 grep의 출력 으로 이동됩니다.

이는 유닉스 철학 원칙을 따릅니다."한 가지 일을 잘하라".

그것들을 하나로 합치다

내 설명에서는 이 변수를 사용 YESTERDAY1하고 YESTERDAY2명령 대체 섹션에서 다루었습니다. 이제 이해할 수 있을 것입니다.

하지만 한 가지가 있습니다. 이것이 사실일지는 의문이지만 자정 무렵의 매우 느린 시스템에서는 이 두 명령 대체를 실행하는 사이의 시간이 우리가 grep원하는 것과 다른 파일 이름 값을 생성할 만큼 충분히 길어질 수 있습니다.

덧붙여서

정말 복잡해지고 어제의 값이 다를 수 있는 문제를 피하고 싶다면 다음을 사용할 수 있습니다.매개변수 확장( ${parameter/pattern/string}) 그게 다야. 먼저 날짜를 변수에 넣으십시오.명령 대체:

YESTERDAY=$(date +%Y-%m-%d --date='1 day ago')

그런 다음 사용매개변수 확장다음과 같이 변수의 한 인스턴스에서 대시를 제거합니다.

grep $YESTERDAY /path/to/file/FILE_PREFIX_${YESTERDAY//-}.dsv | grep -v 'ERROR' | cut -d "|" -f 2 | sed 's/^0/27/'

이렇게 하면 날짜 값을 한 번만 검색하면 되며 (비록 적기는 하지만) 다른 날짜를 얻을 가능성이 없습니다.

추천도서

관련 정보