파일 내용을 복사하고 이전 명령의 출력과 일치하는 경우 몇 줄을 삭제해야 하는 문제가 있습니다. 하지만 지금까지는 파일 라인을 정확히 동일하게 유지하는 데 어려움을 겪고 있습니다. 복사본을 생략하는 것은 영향을 받지 않는 행에서 발생하므로 문제의 일부가 아닌 것처럼 스크립트의 간단한 부분을 가지고 있습니다.
예를 들어:
원본 파일에는 다음이 있습니다.
Testing, resuming text
스크립트를 실행하면 필드는 다음과 같습니다.
Testing, resuming text
나는 다음을 수행하고 있습니다 :
#!/usr/bin/bash
rm /tmp/dest_file
while read line
do
echo $line >> /tmp/dest_file
done < $1
내가 겪고 있는 문제는 탭 형식의 필드로 인해 파일이 달라지는 것입니다.
답변1
이 사이트는 여러 번 나타났습니다 - 참조IFS에 대해 알아보기그리고 관련된 문제. 이 답변에서는 무엇이 잘못될 수 있는지, 그리고 이를 방지하는 방법을 요약하겠습니다. 자세한 내용은 링크된 스레드를 참조하세요.
read line
다음을 수행하십시오.
- 표준 입력에서 첫 번째 바이트(개행 또는 null)를 읽고 데이터를 변수에 넣습니다
line
. - 줄 끝에 있지 않은 백슬래시를 제거합니다. 이중 백슬래시는
\\
단일 백슬래시가 됩니다. 즉, 백슬래시는 개행 문자가 아닌 한 다음 문자를 인용합니다. read
줄 바꿈에서 멈추고 줄 끝의 문자가 a 인 경우\
백슬래시 줄 바꿈 시퀀스를 제거하고 계속 읽으면서 변수에 추가합니다line
. 첫 번째까지 반복: 앞에 백슬래시가 없는 개행 문자, 입력 끝.line
에서 문자로 구성된 가장 긴 접미사를 제거합니다$IFS
. 기본적으로IFS
탭, 공백 및 줄 바꿈이 포함되므로 값 끝에서 ASCII 공백이 제거됩니다line
.line
공백 문자로 구성된 가장 긴 접두사를 제거합니다$IFS
.
예를 들어 입력이 다음과 같은 경우
: hello\
world: :
wibble
그러면 포함(초기 공간 없음)이 read line
발생하며 기본값은 입니다 . (그냥 콜론) 으로 변경 하면 결과는 (시작과 끝의 공백)입니다. 및 공백이 모두 포함된 경우 결과는 (초기 또는 후행 공백 없음)입니다.line
: helloworld: :
IFS
IFS
:
read line
: helloworld:
IFS
:
: helloworld
이를 방지하려면 IFS
null 값으로 설정하세요(설정을 해제하는 것과는 다릅니다). read
명령을 작성해야만 설정할 수 있습니다 IFS= read
(참조:"IFS=;" 대신 "IFS= 읽기"가 자주 사용되는 이유는 무엇입니까?).
백슬래시 처리를 방지하려면 -r
옵션을 에 전달하십시오 read
.
쉘이 zsh가 아닌 경우 입력에 널 바이트가 있으면 후속 문자가 손실됩니다. 쉘은 이진 데이터를 읽도록 설계되지 않았습니다.
따라서 한 번에 한 줄씩 읽는 관용어는 다음과 같습니다.
while IFS= read -r line; do
… # process "$line"
end
변수를 사용할 때 line
다음 사항을 확인하세요.변수 대체에는 항상 큰따옴표를 사용하세요.: "$line"
. 큰따옴표가 없으면 쉘은 먼저 변수 값을 확장한 다음 의 문자가 포함될 때마다 값을 별도의 단어로 나누고 IFS
각 단어는 와일드카드 패턴으로 해석되어 일치하는 파일 목록으로 대체됩니다(일치하는 항목이 없는 경우). 파일에서 스키마는 그대로 유지됩니다. 따라서 echo 'a* b*' | IFS= read -r line; echo $line
입력을 변경하지 않고 그대로 두려면 또는 로 시작하는 현재 디렉터리의 파일 목록으로 확장합니다.a
b
echo 'a* b*' | IFS= read -r line; echo "$line"
또한 이 echo
명령은 때때로 인쇄되는 문자열을 수정한다는 점에 유의하십시오. 정확한 방법은 쉘에 따라 다릅니다. 일부 쉘은 백슬래시 이스케이프를 처리하고 일부 쉘은 옵션을 인식합니다. echo
문자열에 백슬래시가 포함되어 있지 않고 대시( )로 시작하지 않는다는 것을 알고 있는 경우 -
에만 문자열을 그대로 출력할 수 있습니다 . 문자열을 있는 그대로 인쇄하는 안정적이고 이식 가능한 방법
printf '%s\n' "$line"
그러면 문자열 뒤에 개행 문자가 인쇄됩니다. 예를 들어 위 명령에서 개행 문자를 생략 echo
할 수 있습니다 .\n
답변2
변수를 인용하세요:
echo "$line" >> /tmp/dest_file