Wejście:
1
hgh
h2b
h4h
2
ok
koko
lkopk
3
uh
ju
nfjvn
4
Oczekiwany wynik:
1
2
3
4
Tak więc muszę mieć tylko 1., 5., 9., 13. wartość pliku w pliku wyjściowym. Jak to zrobić?
Wejście:
1
hgh
h2b
h4h
2
ok
koko
lkopk
3
uh
ju
nfjvn
4
Oczekiwany wynik:
1
2
3
4
Tak więc muszę mieć tylko 1., 5., 9., 13. wartość pliku w pliku wyjściowym. Jak to zrobić?
Odpowiedzi:
Korzystanie z AWK:
awk '!((NR - 1) % 4)' input > output
Zrozumienie, jak to działa, pozostawia się jako ćwiczenie dla czytelnika.
NR % 4 == 1
byłoby bardziej czytelne IMO.
Używając split
(GNU coreutils):
split -nr/1/4 input > output
-n
generować CHUNKS
pliki wyjściowei CHUNKS
jak
r/K/N
używaj okrągłego rozkładu robin i wysyłaj Kth of N tylko do standardowego wyjścia bez dzielenia linii / rekordówZ GNU sed
:
sed '1~4!d' < input > output
Ze standardem sed
:
sed -n 'p;n;n;n' < input > output
Z 1
oraz 4
w $n
i $i
zmienne:
sed "$n~$i!d" # GNU only
awk -v n="$n" -v i="$i" 'NR >= n && (NR % i) == (n % i)'
Wersja Python, dla zabawy:
with open('input.txt') as f:
for i, line in enumerate(f.readlines()):
if i%4 == 0:
print(line.strip())
enumerate(f)
powinien być w stanie wykonać to zadanie, zużywając mniej pamięci
readlines
(w ten sposób zapisując cały plik do pamięci), możesz użyć, f.readlines()[::4]
aby uzyskać co czwarty wiersz. Więc możesz użyć print(''.join(f.readlines()[::4]))
.
POSIX sed
: ta metoda wykorzystuje posixly sed, dzięki czemu można go uruchamiać wszędzie lub przynajmniej w tych sekwencjach, które szanują posix.
$ sed -ne '
/\n/!{
H;s/.*//;x
}
:loop
$bdone
N;s/\n/&/4
tdone
bloop
:done
s/.//;P
' input.file
Kolejnym jest programowe generowanie kodu sed dla celów skalowalności:
$ code=$(yes n | head -n 4 | paste -sd\; | sed s/n/p/)
$ sed -ne "$code" input.file
Perl
: wypełniamy tablicę A, aż osiągnie rozmiar 4. Następnie drukujemy jego pierwszy element, a także usuwamy tablicę.
$ perl -pe '
$A[@A] = @A ? <> : $_ while @A < 4;
$_ = (splice @A)[0];
' input.file
Zadzwoń za pomocą scriptname filename skip
(4 w twoim przypadku) Działa poprzez wyciągnięcie iter
linii z góry pliku, a następnie wyprowadzenie tylko ostatniego. Następnie zwiększa iter
się skips
i powtarza, o ile wartość iter
nie przekroczyła wartości lines
in file
.
#!/bin/bash
file="$1"
lines=`wc -l < "$file"`
skips="$2" || "4"
iter=1
while [ "$iter" -le "$lines" ]; do
head "$file" -n $iter | tail -n 1
iter=$(( $iter + $skips ))
done
Pure Bash:
mapfile -t lines < input
for (( i=0; i < ${#lines[@]}; i+=4 ))
do printf "%s\n" "${lines[$i]}"
done
mapfile jest wbudowanym dodatkiem w Bash 4, który odczytuje standardowe dane wejściowe do tablicy, o tej nazwie lines
, z jednym wierszem na wpis. -t
Wariant taśmy końcowe nowych linii.
Jeśli chcesz drukować co czwarty wiersz, zaczynając od wiersza 4, możesz to zrobić za pomocą jednej komendy, używając mapfile
opcji wywołania zwrotnego -C
, która uruchamia dostarczony kod co tyle wierszy, z interwałem podanym przez -c
. Bieżący indeks tablicy i następny wiersz do przypisania są podawane do kodu jako argumenty.
mapfile -t -c4 -C 'printf "%.0s%s\n"' < input
To używa printf
wbudowanego; kod formatu %.0s
pomija pierwszy argument (indeks), więc wypisywana jest tylko linia.
Możesz użyć tego samego polecenia, aby wydrukować co czwartą linię, zaczynając od linii 1, 2 lub 3, ale musiałbyś input
przed dodaniem 3, 2 lub 1 linii przed karmieniem jej mapfile
, co moim zdaniem jest bardziej kłopotliwe niż warte .
Działa to również:
mapfile -t lines < input
printf "%s%.0s%.0s%.0s\n" "${lines[@]}"
Tutaj printf
zużywa cztery wpisy tablicy lines
jednocześnie, tylko drukując pierwszy i pomijając pozostałe trzy za pomocą %.0s
. Nie podoba mi się to, ponieważ trzeba ręcznie manipulować ciągiem formatu dla różnych interwałów lub punktów początkowych.
sed -n '1~4p'