2009-10-30 2 views
6

텍스트 파일의 디렉토리를 반복하여 하나의 문서로 결합하려고합니다. 이것은 훌륭하게 작동하지만 텍스트 파일에는 코드 스 니펫이 포함되어 있으며 모든 서식이 왼쪽으로 축소됩니다. 행의 선행 공백이 모두 제거됩니다.읽는 동안 공백을 남김 >> 파일을 한 줄씩 bash로 씁니다.

#!/bin/sh 
OUTPUT="../best_practices.textile" 
FILES="../best-practices/*.textile" 
for f in "$FILES" 
do 
    echo "Processing $f file..." 
    echo "">$OUTPUT 

    cat $f | while read line; do 
     echo "$line">>$OUTPUT 
    done 
    echo >>$OUTPUT 
    echo >>$OUTPUT 
done 

나는 bash 멍청이이지만, 높거나 낮은 검색 후에는 적절한 해결책을 찾을 수 없습니다. 외관상으로는 BASH는 일반적인 공백을 싫어합니다.

답변

3

대신에 :

cat $f | while read line; do 
    echo "$line">>$OUTPUT 
done 

은이 작업을 수행 :

cat $f >>$OUTPUT 

(. 문제의 것을 포함하는 것이 좋을 것 당신이 선으로 가지 라인을해야 할 이유가 있다면)

+0

너무 공백을 없앱니다. 선을 넘기는 공간을 절약 할 수있는 옵션이 더 있는지를보기 위해 줄 단위로 전환했습니다. –

+1

아, 공백을 없애지 않습니다. 고마워요.> –

+1

흥미 롭습니다. 이 대답은 설명없이 두 번 downvoted되었습니다. downvote에가는 경우에, 왜 말하십시오. (그리고 이것이 "이것이 단지 하나의 cat 명령 일 수있다"라고 생각하기 때문입니다 : 1. 파일과 2 사이에 삽입 된 여분의 빈 줄을주의하십시오. 나는 이것이 잘못 설정된 스크립트라고 가정하고 있습니다. 단순함을 위해 실제 버전에는 파일 당 추가 로직이있을 수 있습니다.) –

3

이는 파일을 결합하는 데 지나치게 비싼 방법입니다.

cat ../best-practices/*.textile > ../best_practices.textile 

당신이 당신이 각각의 입력 사이에 줄 바꿈을 산재 할 수 있습니다

awk 'FNR==1{print "">"out.txt"}{print > "out.txt" }' *.textile 

또는

awk 'FNR==1{print ""}{print}' file* > out.txt 
+0

당신은 1 초 만에 나를 때려. –

+1

좋은. 고맙습니다. 저는 Bash를 개념적으로 정말 좋아합니다. 이제 나는 내 애정을 가지고 나의 지식을 얻을 필요가 있습니다. 환호 –

+0

내 문서의 제목은 아이러니하게도 나를 때리며 .. heh –

1

당신이 연결할 각 파일, 사용 AWK에 빈 (줄 바꿈)를 추가하려면 원래 스크립트에서 수행 한 것처럼 파일 이름 :

for f in $FILES; do echo -ne '\n\n' | cat "$f" -; done > $OUTPUT 

$FILES은이 작업을 위해 인용 부호가 붙지 않습니다 (그렇지 않으면 여분의 줄 바꿈은 모든 출력 끝에서 한 번만 나타납니다). 그러나 파일 이름에 공백이 있으면이를 보호하기 위해 $f을 따옴표로 묶어야합니다.

40

다른 사람들도 지적했듯이, read-echo 루프 대신에 cat이나 awk를 사용하는 것이 훨씬 더 좋은 방법입니다 - 공백을 제거하는 문제 (그리고 당신이 우연히 만난 적이없는 몇 가지 다른 것들)를 피하십시오. , 더 빨리 달리고 적어도 cat은 간단하게 코드입니다. 그럼에도 불구하고, 나는 read-echo 루프를 제대로 작동시키는 데에 찔림을 사고 싶다.

첫째, 공백을 제거하는 문제 : 읽기 명령이 자동으로 앞뒤 공백을 자릅니다. IFS 변수를 공백으로 설정하여 공백의 정의를 변경하면이 문제를 해결할 수 있습니다. 또한 read는 줄 끝의 백 슬래시는 다음 줄이 연속이라는 것을 의미하며이 줄과 함께 이어져야 함을 전제로합니다. 이 문제를 해결하려면 -r (원시) 플래그를 사용하십시오. 세 번째 문제는 많은 에코 구현이 이스케이프 시퀀스를 문자열에서 해석한다는 것입니다 (예 : \ n이 실제 줄 바꿈 문자로 바뀔 수 있음). 이 문제를 해결하려면 대신 printf를 사용하십시오. 마지막으로, 일반적인 스크립팅 위생 규칙처럼, 실제로 필요하지 않을 때는 cat을 사용하지 않아야합니다. 대신 입력 리디렉션을 사용하십시오. 이러한 변화와 함께, 내부 루프는 다음과 같습니다

while IFS='' read -r line; do 
    printf "%s\n" "$line">>$OUTPUT 
done <$f 

는 ... 또한 주변의 스크립트와 다른 몇 가지 문제가있다 : 자료 .textile 파일 목록으로 파일을 정의하려고 라인이있다 그 주위에 따옴표가 붙어있어 실제 파일 목록으로 확장되지 않습니다.이 작업을 수행하는 가장 좋은 방법은 배열을 사용하는 것입니다 경우 큰 따옴표에 있어야 파일 이름 중 하나를

FILES=(../best-practices/*.textile) 
... 
for f in "${FILES[@]}" 

(와 $ F의 모든 항목을 가지고 그들에 공백이나 기타 이상한 문자가 - 정말해야 $ OUTPUT도 마찬가지다. 스크립트에서 정의 된 것이므로 실제로 제거하면 안전하다.)

마지막으로 출력 파일을 모두 지우는 루프 오버 파일 맨 위에 echo "">$OUTPUT이있다. 시간이 끝날 때까지 (즉, 마지막 .textile 파일 만 포함); 이것은 루프 앞에 이동해야합니다. 여기에 파일의 시작 부분에 빈 줄을 하나 넣거나 파일 사이에 빈 줄을 하나 넣으려는 의도가 있는지 모르겠다. 적절한 교체가 있습니다. 어쨌든, 여기에이 모든 문제를 해결 한 후와 내가 할 수있는 무엇이다 :

#!/bin/sh 
OUTPUT="../best_practices.textile" 
FILES=(../best-practices/*.textile) 

: >"$OUTPUT" 
for f in "${FILES[@]}" 
do 
    echo "Processing $f file..." 
    echo >>"$OUTPUT" 

    while IFS='' read -r line; do 
    printf "%s\n" "$line">>"$OUTPUT" 
    done <"$f" 

    echo >>"$OUTPUT" 
    echo >>"$OUTPUT" 
done 
+0

이 고든에 시간을 할애 해 주셔서 감사합니다. 매우 유익했습니다. –

+0

끝내 주셔서 감사합니다. 덕분에 –

+0

여기가 가장 좋습니다! 너무 명확하게 설명 할 시간을 내 주셔서 감사드립니다. :) – Arnlen

0

정답은, IMO, this입니다, 아래의 재현 :

while IFS= read line; do 
    check=${line:0:1} 
done < file.txt 

참고이 상황을 돌볼거야 여기서 입력은 실제 파일뿐만 아니라 다른 명령에서 파이프됩니다.

아래와 같이 리디렉션을 단순화 할 수도 있습니다.

#!/bin/bash 
OUTPUT="../best_practices.textile" 
FILES="../best-practices/*.textile" 
for f in "$FILES" 
do 
    echo "Processing $f file..." 
    { 
    echo 

    while IFS= read line; do 
     echo "$line" 
    done < $f 
    echo 
    echo; 
    } > $OUTPUT 
done 
관련 문제