Grepping, awking, sedding 및 파이프라인은 명령줄이나 셸 스크립트(통칭하여필터지금부터).
기본적으로 "표준" Unix CLI 프로그램과 셸 내장(통칭하여주문하다이제부터) 필터가 제대로 작동하려면 각 필터 단계에서 정확히 예상되는 stdin, stdout 및 stderr 형식이 필요합니다. 아래에서는 일부 명령의 정확한 예상 형식을 해당 명령의 API라고 부릅니다.
웹 개발 배경을 가진 사람으로서 저는 이러한 종류의 데이터 수집 및 데이터 처리를 기술적으로 연관시킵니다.웹 스크래핑- 이 기술은 데이터 표현에 약간의 변화가 있을 때마다 매우 불안정합니다.
현재 문제는 Unix 명령 API의 안정성과 관련이 있습니다.
- Unix 계열 운영 체제의 명령은 입력 및 출력의 공식 표준화를 따르나요?
- 역사적으로 일부 중요한 명령을 업데이트하면 해당 명령의 이전 버전으로 구축된 일부 필터의 기능이 중단된 경우가 있습니까?
- Unix 명령은 시간이 지나면서 성숙해져서 일부 필터를 깨뜨릴 수 있는 방식으로 명령을 변경하는 것이 절대 불가능해졌습니까?
- 명령 API의 변경으로 인해 필터가 깨질 수 있는 경우 개발자로서 이 문제로부터 필터를 보호하려면 어떻게 해야 합니까?
답변1
POSIX 2008 표준에는 설명하는 섹션이 있습니다."셸 및 유틸리티". 일반적으로 말해서, 이를 고수한다면 스크립트는 지원 중단 가능성을 제외하면 상당히 미래 지향적이어야 하지만 이러한 일이 하루아침에 발생하는 경우는 거의 없으므로 스크립트를 업데이트할 충분한 시간이 있어야 합니다.
단일 유틸리티의 출력 형식이 플랫폼과 버전에 따라 크게 달라지는 경우 POSIX 표준에는 보장되고 예측 가능한 출력 형식을 지정하는 -p
일반적으로 또는 라고 불리는 옵션이 포함될 수 있습니다. -P
이에 대한 예는 다음과 같습니다.time
유용, 구현은 매우 다양합니다. 안정적인 API/출력 형식이 필요한 경우 time -p
.
POSIX 표준에서 다루지 않는 필터 유틸리티를 사용해야 하는 경우 웹 스크래핑을 수행할 때 원격 웹 개발자의 손에 달려 있는 것처럼 배포 패키저/업스트림 개발자의 손에 거의 달려 있습니다.
답변2
제 경험을 바탕으로 답변해드리도록 노력하겠습니다.
명령은 실제로 공식적인 사양을 따르지는 않지만 행 중심 텍스트를 사용하고 생성하기 위한 요구 사항을 준수합니다.
물론이죠. GNU 유틸리티가 사실상의 표준이 되기 전에는 많은 벤더들이 특히
ps
및ls
. 이로 인해 많은 고통이 발생했습니다. 오늘날 HP만이 매우 엉뚱한 명령을 제공합니다. 역사적으로 BSD(Berkeley Software Distribution) 유틸리티는 과거와 크게 달라졌습니다. POSIX 사양은 과거와는 다르지만 현재는 널리 받아들여지고 있습니다.Unix 명령은 확실히 시간이 지나면서 성숙해졌습니다. 이전 버전용으로 작성된 일부 스크립트를 중단하는 것은 여전히 불가능하지 않습니다. 텍스트 파일의 인코딩으로 UTF-8을 사용하는 최근 추세를 고려하십시오. 이 변경에는 기본 유틸리티의 변경이 필요합니다. 예를 들어
tr
과거에는 간단한 텍스트가 거의 항상 ASCII(또는 이에 가깝습니다)이므로 대문자와 소문자는 숫자 범위를 형성했습니다. UTF-8에서는 더 이상 그렇지 않습니다. 따라서tr
"대문자" 또는 "영숫자"와 같은 항목을 지정하기 위해 다른 명령줄 옵션이 허용됩니다.필터를 "강화"하는 가장 좋은 방법 중 하나는 특정 텍스트 레이아웃에 의존하지 않는 것입니다. 예를 들어, 하지 마십시오
cut -c10-24
. 행의 위치에 따라 다릅니다. 대신cut -f2
탭으로 구분된 두 번째 필드를 제거하는 를 사용하세요.awk
기본적으로 입력 줄을 $1, $2, $3...으로 공백으로 구분하여 나눕니다. 열 위치와 같은 낮은 수준의 개념보다는 "필드"와 같은 높은 수준의 개념을 사용하십시오. 또한 정규식을 사용하십시오.sed
둘awk
다 정규식을 사용하여 입력 차이에 상관 없는 작업을 수행할 수 있습니다. 또 다른 비결은 필터가 까다로울 수 있는 형식으로 입력을 처리하는 것입니다.tr -cs '[a-zA-z0-9]' '[\n]'
구두점 없이 텍스트를 한 줄에 한 단어로 나누는 데 사용됩니다 . 이 경우 입력 텍스트가 어떻게 보이는지는 신경 쓰지 않아도 됩니다.
답변3
먼저 귀하의 질문에 대한 매우 간단한 답변입니다.
- 입력/출력 규칙의 공식 표준화:아니요
- 출력 변경으로 인한 과거 피해:예
- 미래의 필터를 깨는 것은 절대 불가능합니다.아니요
- 변화로부터 나 자신을 보호하는 방법:보수적으로 행동하세요
"API"라고 말할 때 사용하는 용어는 좋든 나쁘든 필터 입력/출력 규칙이 너무 형식적이라는 것을 의미합니다. 매우 광범위하게("매우"를 의미함) 쉽게 필터링할 수 있는 데이터에 대한 주요 규칙은 다음과 같습니다.
- 각 입력 라인은 완전한 레코드입니다.
- 각 레코드에서 필드는 알려진 구분 기호로 구분됩니다.
일반적인 예는 /etc/passwd 형식입니다. 그러나 이러한 기본 규칙은 엄격하게 준수되는 것보다 어느 정도 위반되는 경우가 더 많습니다.
- 여러 줄 입력 형식을 구문 분석할 수 있는 많은 필터(일반적으로 awk 또는 Perl로 작성됨)가 있습니다.
- 잘 정의된 필드 구조가 없는 입력 패턴(예: /var/log/messages)이 많으므로 보다 일반적인 정규식 기반 기술을 사용해야 합니다.
네 번째 질문인 출력 구조 변경으로부터 자신을 보호하는 방법은 실제로 할 수 있는 유일한 질문입니다.
- ~처럼@jw013 님이 말씀하셨습니다., posix 표준의 내용을 확인하세요. 물론 posix는 입력 소스로 사용하려는 모든 명령을 지정하지 않습니다.
- 스크립트를 이식 가능하게 하려면 설치한 명령 버전의 기능을 피하십시오. 예를 들어, 표준 Unix 명령의 많은 GNU 버전에는 비표준 확장이 있습니다. 이는 유용할 수 있지만 최대의 이식성을 원한다면 피해야 합니다.
- 명령 매개변수의 하위 집합과 출력 형식이 플랫폼 전반에 걸쳐 안정적인 경향이 있는지 이해해 보세요. 안타깝게도 이러한 차이점은 비공식적으로도 어디에도 문서화되어 있지 않기 때문에 시간이 지남에 따라 여러 플랫폼에 액세스해야 합니다.
결국, 걱정하는 문제로부터 자신을 완전히 보호할 수 없으며 명령이 수행해야 하는 작업에 대한 "명확한" 설명을 찾을 곳이 없습니다. 많은 쉘 스크립트, 특히 개인용 또는 소규모 사용을 위해 작성된 스크립트의 경우 이는 전혀 문제가 되지 않습니다.
답변4
사실상의 IO 표준(공백 및 null로 구분된 출력)만 있습니다.
호환성에 관해서는 일반적으로 개별 필터의 버전 번호를 확인합니다. 많이 변경된 것은 아니지만 새로운 기능을 사용하고 여전히 이전 버전에서 스크립트를 실행하려면 어떻게든 "ifdef"해야 합니다. 실제로 테스트 사례를 수동으로 작성하는 것 외에는 기능 보고 메커니즘이 없습니다.