Входные данные:
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 of N на стандартный вывод без разделения строк / записейС 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 и поэтому может использоваться везде, или, по крайней мере, те 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'