다음 진술이 무엇을 하는지 나에게 설명해 주실 수 있나요?
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')
중첩을 허용하고 이스케이프 측면에서 덜 번거로운 후자(및 최신) 형식을 입력하여 얻는 것과 동일한 효과 입니다 .
- 두 번째 호출(pathname의 호출)은 형식을 다음과 같이 조정합니다.
효과명령 대체명령줄에서 다음과 같은 것을 할당합니다.
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.dsv
grep은 파일에서 어제 날짜 값을 찾아서/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
다음 명령에 연결합니다.stdout
stdin
이렇게 하면 첫 번째 읽기 파일의 출력이 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/'
이렇게 하면 날짜 값을 한 번만 검색하면 되며 (비록 적기는 하지만) 다른 날짜를 얻을 가능성이 없습니다.
추천도서
man
시스템의 Bash 페이지 또는여기- 이것배쉬 해커 위키
- 고급 Bash 스크립팅 가이드