미묘한 GoTchas를 처리하는 한 쉘 스크립트에서 Linux 텍스트 파일 행의 내용을 읽는 것은 꽤 쉽습니다. 안전한 방식으로하는 방법은 다음과 같습니다.
파일, 텍스트 및 관용구
각 프로그래밍 언어에는 세트의 관용구가 있습니다. 이들은 일반적인 작업 세트를 수행하는 표준, 프릴 없음 방식입니다. 프로그래머가 작동하는 언어의 기능 중 하나를 사용하는 기본 또는 기본 방법입니다. 그들은 프로그래머의 정신 청사진의 툴킷의 일부가됩니다.
파일에서 데이터를 읽고 루프를 사용한 작업을 읽고 두 변수의 값을 교환하는 것과 같은 조치가 좋은 예입니다. 프로그래머는 일반 또는 바닐라 방식으로 끝을 달성하는 적어도 한 가지 방법을 알 수 있습니다. 아마도 그것은 그 밖의 요구 사항에 대해 충분할 것입니다. 아니면 개발중인 특정 솔루션에보다 효율적이거나 적용 할 수 있도록 코드를 장식 할 수 있습니다. 그러나 빌딩 블록 관용구가 손가락 끝에서 훌륭한 출발점이 있습니다.
한 언어로 관용구를 알고 이해하는 것은 새로운 프로그래밍 언어를 쉽게 집어들 수 있습니다. 한 언어로 구성되는지를 알고 다른 언어로 가장 가까운 것으로 보는 방법을 아는 것이 이미 알고있는 프로그래밍 언어와 당신이 배우고있는 사람의 유사점과 차이점을 인식하는 좋은 방법입니다.
파일에서 라인 읽기 : 원 라이너
Bash에서는 A를 사용할 수 있습니다
동안
명령 줄에 루프를 루프하여 파일에서 각 텍스트 줄 행을 읽고 뭔가를 수행하십시오. 텍스트 파일을 "data.txt"라고합니다. 그것은 올해의 개월 목록을 보유하고 있습니다.
1 월 2 월 3 월 ...에 ...에 십월 십일월 12 월
우리의 간단한 원 라이너는 다음과 같습니다.
판독 선; echo $ line; 완료 & lt; data.txt
NS
동안
루프는 파일에서 선을 읽고 작은 프로그램의 실행 흐름이 루프의 본문으로 전달됩니다. NS
에코
명령은 터미널 창에 텍스트 줄을 씁니다. 읽을 수있는 줄이 없으면 읽기 시도가 실패하고 루프가 완료됩니다.
하나의 깔끔한 트릭이 능력입니다 파일을 루프로 리디렉션하려면 ...에 다른 프로그래밍 언어에서는 파일을 열고 읽어 읽어야하며 완료 할 때 다시 닫아야합니다. Bash를 사용하면 파일 리디렉션을 사용하고 쉘이 해당 저수준의 모든 것들을 모두 사용할 수있게하십시오.
물론,이 한 라이너는 끔찍하게 유용하지 않습니다. Linux는 이미 제공합니다
고양이
Command, 우리를 위해 정확히 그렇게합니다. 우리는 세 글자 명령을 대체 할 수있는 긴 권선을 만들었습니다. 그러나 그것은 파일에서 읽는 원칙을 눈에 띄게 보여줍니다.
그것은 충분히 잘 작동합니다. 달의 이름이 포함 된 다른 텍스트 파일이 있다고 가정 해보십시오. 이 파일에서는 각 행에 개행 문자에 대한 이스케이프 시퀀스가 추가되었습니다. 우리는 "data2.txt"라고 부릅니다.
1 월 \ N. 2 월 \ N. 3 월 \ N. ...에 ...에 10 월 \ N. 11 월 \ N. 12 월 \ N
우리의 새로운 파일에서 우리의 원 라이너를 사용합시다.
판독 선; echo $ line; 완료 & lt; data2.txt
백 슬래시 이스케이프 문자 "
\
"폐기되었습니다. 결과는 "n"이 각 줄에 추가되었습니다. Bash는 백 슬래시를 시작으로 해석하고 있습니다.
이스케이프 시퀀스
...에 종종 우리는 bash가 읽는 것을 해석하기를 원하지 않습니다. 전체 백 슬래시 이스케이프 시퀀스에서 라인을 읽는 것이 더 편리 할 수 있으며 모든 코드 내에서 자신을 구문 분석하거나 교체 할 것을 선택할 수 있습니다.
텍스트 줄에 의미있는 처리 또는 구문 분석을하고 싶다면 스크립트를 사용해야합니다.
스크립트가있는 파일에서 줄을 읽습니다
우리 스크립트가 있습니다. 그것은 "script1.sh"라고 불립니다.
#! / bin / bash
카운터 = 0
IFS = 판독 LINEFROMFILE ] || [ " $ {라인} " ] ];
((((( [98 카운터 ++ ))
에코 "액세스 라인 $ 카운터 : $ {lineFromFile} "
DONE & lt; $ 1 "$ 1
우리는 변수를 설정했습니다
카운터
0으로, 우리는 우리를 정의합니다
동안
고리.
온라인 행의 첫 번째 문은입니다
ifs = ''
...에
Ifs.
내부 필드 분리기를 의미합니다. Bash가 Word 경계를 식별하는 데 사용하는 값을 보유하고 있습니다. 기본적으로 읽기 명령은 선행 및 후행 공백을 벗어냅니다. 파일에서 정확하게 라인을 읽으려면 설정해야합니다.
Ifs.
빈 문자열이됩니다.
우리는 루프의 밖에서 한 번이를 설정할 수 있습니다.
카운터
...에 그러나 더 복잡한 스크립트로, 특히 많은 사용자 정의 함수가있는 것들이 가능합니다.
Ifs.
스크립트의 다른 값으로 설정할 수 있습니다. 그것을 보장합니다
Ifs.
매번 빈 문자열로 설정됩니다
동안
루프 반복적 인 것은 우리가 그 행동이 무엇인지 알 수 있도록 보장합니다.
우리는 텍스트 줄을 변수로 읽을 것입니다.
linefromfile.
...에 우리는을 사용하고 있습니다
-NS
(백 슬래시를 무시하는 옵션을 사용하여 정상 문자로서 백 슬래시를 읽으십시오) 옵션. 그들은 다른 캐릭터처럼 취급 될 것이며 특별한 치료를받지 못할 것입니다.
그를 만족시키는 두 가지 조건이 있습니다
동안
루프를 루프하고 루프 본문에 의해 처리 할 수있게하십시오.
-
-r linefromfile을 읽습니다: 텍스트 줄이 파일에서 성공적으로 읽을 때읽다명령은 성공 신호를 그에게 보냅니다동안, 그리고동안루프는 실행 흐름을 루프 본문으로 전달합니다. 그게 주목하십시오읽다명령은 A를 볼 필요가 있습니다 개행 문자 텍스트 줄 끝에 성공적인 읽기를 고려하십시오. 파일이 A. 포지 믹스 호환 텍스트 파일, 마지막 줄에는 개행 문자가 포함되어 있지 않을 수 있습니다 ...에 그 경우읽다명령은 그를 본다 파일 마커의 끝 (eof) 라인이 개행에 의해 종료되기 전에 ~ 아니다 그것을 성공적으로 취급하십시오. 그런 일이 발생하면 텍스트의 마지막 줄은 루프의 본문에 전달되지 않으며 처리되지 않습니다. -
[-n "$ {lineFromFile}"]: POSIX 호환 파일을 처리하기 위해 추가 작업을 수행해야합니다. 이 비교는 파일에서 읽은 텍스트를 확인합니다. 개행 문자로 종료되지 않으면이 비교는 여전히 성공을 반환합니다.동안고리. 이렇게하면 트레일 링 라인 파편이 루프 본문에 의해 처리되도록합니다.
이 두 조항은 논리 연산자로 구분됩니다. "
||
"그렇다면
어느 하나
절을 반환하면 검색된 텍스트가 루프 본문에 의해 처리되며 NewLine 문자가 있든 아니든 간행됩니다.
우리 루프의 몸에서 우리는
카운터
가변적으로 사용하고 사용합니다
에코
일부 출력을 터미널 창으로 보내려면. 각 행의 줄 번호와 텍스트가 표시됩니다.
우리는 여전히 리디렉션 트릭을 사용하여 파일을 루프로 리디렉션 할 수 있습니다. 이 경우 스크립트에 전달 된 첫 번째 명령 줄 매개 변수의 이름을 보유하는 변수 인 $ 1을 리디렉션합니다. 이 트릭을 사용하여 스크립트가 작업 할 데이터 파일의 이름을 쉽게 전달할 수 있습니다.
스크립트를 복사하여 편집기에 넣고 파일 이름 "script1.sh"로 저장하십시오. 사용
chmod.
명령
그것을 실행할 수 있도록합니다
...에
chmod + x script1.sh
우리의 스크립트가 Data2.txt 텍스트 파일과 그 안에 포함 된 백 슬래시를 만드는 것을 보도록하십시오.
./ script1.sh data2.txt
줄의 모든 문자가 축 어림이 표시됩니다. 백 슬래시는 이스케이프 문자로 해석되지 않습니다. 그들은 정기적 인 문자로 인쇄됩니다.
라인을 함수로 전달합니다
우리는 여전히 텍스트를 화면에 반영합니다. 실제 프로그래밍 시나리오에서는 텍스트 라인으로 더 흥미로운 일을 할 것입니다. 대부분의 경우 다른 기능에서 라인의 추가 처리를 처리하는 것이 좋습니다.
우리가 어떻게 할 수있는 방법은 다음과 같습니다. 이것은 "script2.sh"입니다.
우리는 우리를 정의합니다
카운터
변수와 같이 변수가 발생한 다음 호출 된 함수를 정의합니다.
process_line ()
...에 함수의 정의가 나타나야합니다
~ 전에
이 기능은 먼저 스크립트에서 호출됩니다.
우리의 기능은 각 반복에 새로 읽는 텍스트 줄을 전달할 것입니다.
동안
고리. 이 값은 함수 내에서 해당 값에 액세스 할 수 있습니다.
$ 1.
변하기 쉬운. 기능에 두 가지 변수가 전달 된 경우 해당 값에 액세스 할 수 있습니다.
$ 1.
그리고
$ 2.
더 많은 변수를 위해 등등.
W.
마리
루프는 주로 동일합니다. 루프 본문 안에는 하나의 변화가 있습니다. NS
에코
라인은 그 전화로 대체되었습니다
process_line ()
기능. 호출 할 때 "()" "괄호를 사용하지 않아도됩니다.
텍스트 줄을 보유하는 변수의 이름,
linefromfile.
, 함수에 전달 될 때 따옴표로 묶여 있습니다. 이것은 그들 안에 공백이있는 라인을 위해 따옴표가 없으면 첫 번째 단어는
$ 1.
이 기능으로 두 번째 단어는 다음으로 간주됩니다.
$ 2.
, 등등. 따옴표를 사용하면 전체 텍스트 줄이 완전히 처리되도록합니다.
$ 1.
...에 이것은 이것입니다
~ 아니다
똑같다
$ 1.
이는 스크립트에 전달 된 동일한 데이터 파일을 보유합니다.
때문에
카운터
스크립트의 본문에 선언되었으며 함수 안에 있지는 않고 참조 할 수 있습니다.
process_line ()
기능.
위의 스크립트를 편집기에 복사하거나 입력하고 파일 이름 "script2.sh"로 저장하십시오. 그것을 실행 가능하게 만드십시오
chmod.
:
chmod + x script2.sh
이제 우리는 그것을 실행하고 새로운 데이터 파일 인 "data3.txt"로 전달할 수 있습니다. 이것은 그것의 개월의 목록이고, 그 위에 많은 단어가있는 한 줄이 있습니다.
1 월 2 월 3 월 ...에 ...에 십월 11 월 \ Nmore 텍스트 "라인의 끝에" 12 월
우리의 명령은 다음과 같습니다.
./ script2.sh data3.txt
라인은 파일에서 읽혀서 하나씩 전달됩니다.
process_line ()
기능. 모든 선은 백 스페이스, 따옴표 및 여러 단어가있는 홀수를 포함하여 올바르게 표시됩니다.
빌딩 블록이 유용합니다
관용구가 그 언어에 고유 한 무언가를 포함해야한다고 말하는 생각의 기차가 있습니다. 그것은 내가 가입하는 믿음이 아닙니다. 중요한 것은 언어를 잘 활용하고 기억하기 쉽고 코드에서 일부 기능을 구현하는 안정적이고 견고한 방법을 제공한다는 것입니다.