Вхід:
1
hgh
h2b
h4h
2
ok
koko
lkopk
3
uh
ju
nfjvn
4
Очікуваний вихід:
1
2
3
4
Отже, у вихідному файлі мені потрібно мати лише 1-е, 5-е, 9-е, 13-е значення. Як це зробити?
Вхід:
1
hgh
h2b
h4h
2
ok
koko
lkopk
3
uh
ju
nfjvn
4
Очікуваний вихід:
1
2
3
4
Отже, у вихідному файлі мені потрібно мати лише 1-е, 5-е, 9-е, 13-е значення. Як це зробити?
Відповіді:
Використання AWK:
awk '!((NR - 1) % 4)' input > output
З'ясування того, як це працює, залишається вправою для читача.
NR % 4 == 1було б більш розбірливим ІМО.
Використання split (GNU coreutils):
split -nr/1/4 input > output
-nгенерувати CHUNKSвихідні файлиі CHUNKSяк
r/K/N використовувати круговий розподіл роботів і виводити тільки Kth N на stdout без розбиття рядків / записівЗ GNU sed:
sed '1~4!d' < input > output
Зі стандартними sed:
sed -n 'p;n;n;n' < input > output
З 1і 4в $nі $iзмінними:
sed "$n~$i!d" # GNU only
awk -v n="$n" -v i="$i" 'NR >= n && (NR % i) == (n % i)'
Версія Python, просто для розваги:
with open('input.txt') as f:
for i, line in enumerate(f.readlines()):
if i%4 == 0:
print(line.strip())
enumerate(f)повинні вміти виконувати роботу, споживаючи менше пам’яті
readlines(отже, урізавши весь файл в пам'ять), ви можете використовувати f.readlines()[::4]кожен четвертий рядок. Тож можна використовувати print(''.join(f.readlines()[::4])).
POSIX sed: у цьому методі використовується posixly sed, і тому його можна виконувати скрізь або принаймні ті набори, які поважають posix.
$ sed -ne '
/\n/!{
H;s/.*//;x
}
:loop
$bdone
N;s/\n/&/4
tdone
bloop
:done
s/.//;P
' input.file
Ще одне програмне генерування коду sed для цілей масштабування:
$ code=$(yes n | head -n 4 | paste -sd\; | sed s/n/p/)
$ sed -ne "$code" input.file
Perl: ми заповнюємо масив A до розміру 4. Потім друкуємо його перший елемент і також очищаємо масив.
$ perl -pe '
$A[@A] = @A ? <> : $_ while @A < 4;
$_ = (splice @A)[0];
' input.file
Дзвінок за допомогою scriptname filename skip(4 у вашому випадку) Він працює, витягуючи iterрядки зверху файлу, а потім виводячи лише останню. Потім він збільшується iterна skipsі повторюється до тих пір, поки значення iterне перевищило значення linesв 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
Чистий баш:
mapfile -t lines < input
for (( i=0; i < ${#lines[@]}; i+=4 ))
do printf "%s\n" "${lines[$i]}"
done
mapfile - це вбудований додаток у Bash 4, який зчитує стандартний вхід у масив, названий тут lines, з одним рядком на запис. -tВаріант смужки остаточного перекладу рядка.
Якщо ви хочете надрукувати кожен четвертий рядок, починаючи з рядка 4, ви можете зробити це в одній команді, використовуючи mapfileопцію зворотного виклику -C, яка запускає наданий код кожні стільки рядків, з інтервалом, заданим символом -c. Поточний індекс масиву та наступний рядок, який буде призначений, надаються коду як аргументи.
mapfile -t -c4 -C 'printf "%.0s%s\n"' < input
Для цього використовується printfвбудований; код формату %.0sпридушує перший аргумент (індекс), тому друкується лише рядок.
Ви можете використовувати одну і ту ж команду для друку кожного четвертого рядка, починаючи з рядка 1, 2 або 3, але вам доведеться додати 3, 2 або 1 рядки до того, inputяк подавати його mapfile, що, на мою думку, є більше клопоту, ніж варто .
Це також працює:
mapfile -t lines < input
printf "%s%.0s%.0s%.0s\n" "${lines[@]}"
Тут використовується одночасно printfчотири записи масиву lines, тільки друкується перший і пропускається інші три %.0s. Мені це не подобається, оскільки вам доведеться вручну поспілкуватися з рядком формату для різних інтервалів або початкових точок.
sed -n '1~4p'