it-swarm-tr.com

Bir dosyanın satırları arasında nasıl döngü yapılır?

Diyelim ki bu dosyam var:

hello
world
hello world

Bu program

#!/bin/bash

for i in $(cat $1); do
    echo "tester: $i"
done

çıktılar

tester: hello
tester: world
tester: hello
tester: world

Her bir satırda for yinelemesini, boşluk alanlarını ayrı ayrı görmezden gelmek istiyorum, yani son iki satırın

tester: hello world

for i in "$(cat $1)"; tırnak işaretlerinin kullanılması i dosyasının tamamına aynı anda atanmasına neden olur. Neyi değiştirmeliyim?

63
Tobias Kienzler

for ve IFS ile:

#!/bin/bash

IFS=$'\n'       # make newlines the only separator
set -f          # disable globbing
for i in $(cat < "$1"); do
  echo "tester: $i"
done

Bununla birlikte, boş satırları atlayacak yeni satır bir IFS-beyaz boşluk karakteri olduğundan, sıraları 1 olarak sayılır ve önde gelen ve sondaki satırlar görmezden geldi. zsh ve ksh93 (bash değil), IFS=$'\n\n' için yeni satırın özel olarak ele alınmaması gerekir, ancak tüm sondaki satırsonu karakterlerinin (boş satırları da içerecek şekilde) her zaman komut tarafından kaldırılacağını unutmayın ikame.

Veya read (daha fazla cat ile):

#!/bin/bash

while IFS= read -r line; do
  echo "tester: $line"
done < "$1"

Orada, boş satırlar korunur, ancak bir satırsonu karakteri tarafından uygun şekilde sınırlandırılmamışsa son satırı atlayacağını unutmayın.

76
wag

Değer için, bunu sık sık yapmam gerekiyor ve while IFS= read..., bu yüzden bash profilimde aşağıdaki işlevi tanımladım:

# iterate the line of a file and call input function
iterlines() {
    (( $# < 2 )) && { echo "Usage: iterlines <File> <Callback>"; return; }
    local File=$1
    local Func=$2
    n=$(cat "$File" | wc -l)
    for (( i=1; i<=n; i++ )); do
        "$Func" "$(sed "${i}q;d" "$File")"
    done
}

Bu işlev önce dosyadaki satır sayısını belirler, ardından satır sonundaki satırı ayıklamak için sed kullanır ve her satırı belirli bir işleve tek bir dize bağımsız değişkeni olarak iletir. Sanırım bu büyük dosyalar için gerçekten verimsiz olabilir, ama bu benim için bir sorun değildi (tabii ki bu karşılama nasıl iyileştirilebileceğine dair öneriler).

Kullanımı oldukça tatlı IMO:

>> cat example.txt # note the use of spaces, whitespace, etc.
a/path

This is a sentence.
"wi\th quotes"
$End
>> iterlines example.txt echo # preserves quotes, $ and whitespace
a/path

This is a sentence.
"wi\th quotes"
$End
>> x() { echo "$#"; }; iterlines example.txt x # line always passed as single input string
1
1 
1
1
1
1
Jonathan H