Entrada:
1
hgh
h2b
h4h
2
ok
koko
lkopk
3
uh
ju
nfjvn
4
Saída esperada:
1
2
3
4
Então, eu preciso ter apenas o valor 1, 5, 9, 13 do arquivo no arquivo de saída. Como fazer isso?
Entrada:
1
hgh
h2b
h4h
2
ok
koko
lkopk
3
uh
ju
nfjvn
4
Saída esperada:
1
2
3
4
Então, eu preciso ter apenas o valor 1, 5, 9, 13 do arquivo no arquivo de saída. Como fazer isso?
Respostas:
Usando o AWK:
awk '!((NR - 1) % 4)' input > output
Descobrir como isso funciona é deixado como um exercício para o leitor.
NR % 4 == 1
seria IMO mais legível.
Usando split
(GNU coreutils):
split -nr/1/4 input > output
-n
gerar CHUNKS
arquivos de saídae CHUNKS
como
r/K/N
use a distribuição round robin e apenas produza Kth de N no stdout sem dividir linhas / registrosCom o GNU sed
:
sed '1~4!d' < input > output
Com padrão sed
:
sed -n 'p;n;n;n' < input > output
Com 1
e 4
dentro $n
e $i
variáveis:
sed "$n~$i!d" # GNU only
awk -v n="$n" -v i="$i" 'NR >= n && (NR % i) == (n % i)'
Versão Python, apenas por diversão:
with open('input.txt') as f:
for i, line in enumerate(f.readlines()):
if i%4 == 0:
print(line.strip())
enumerate(f)
deve ser capaz de fazer o trabalho enquanto consome menos memória
readlines
(portanto, colocar o arquivo inteiro na memória), use-o f.readlines()[::4]
para obter cada quarta linha. Então você pode usar print(''.join(f.readlines()[::4]))
.
POSIX sed
: esse método usa o posixly sed e pode ser executado em qualquer lugar ou pelo menos nos seds que respeitam o posix.
$ sed -ne '
/\n/!{
H;s/.*//;x
}
:loop
$bdone
N;s/\n/&/4
tdone
bloop
:done
s/.//;P
' input.file
Outra é uma geração programática de código sed para fins de escalabilidade:
$ code=$(yes n | head -n 4 | paste -sd\; | sed s/n/p/)
$ sed -ne "$code" input.file
Perl
: preenchemos o array A até ele ter 4 de tamanho. Em seguida, imprimimos seu primeiro elemento e também limpamos a matriz.
$ perl -pe '
$A[@A] = @A ? <> : $_ while @A < 4;
$_ = (splice @A)[0];
' input.file
Ligue com scriptname filename skip
(4 no seu caso). Ele funciona puxando as iter
linhas da parte superior do arquivo e depois apenas produzindo a última. Em seguida, incrementos iter
por skips
e repete, desde que o valor de iter
não ultrapassou o lines
no 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
O mapfile é um built -in adicionado no Bash 4 que lê a entrada padrão em uma matriz, chamada aqui lines
, com uma linha por entrada. A -t
opção retira as novas linhas finais.
Se você deseja imprimir cada quarta linha começando na linha 4, é possível fazer isso em um comando usando mapfile
a opção de retorno de chamada -C
, que executa o código fornecido a cada tantas linhas, com o intervalo fornecido por -c
. O índice atual da matriz e a próxima linha a ser atribuída são fornecidos ao código como argumentos.
mapfile -t -c4 -C 'printf "%.0s%s\n"' < input
Isso usa o printf
builtin; o código de formato %.0s
suprime o primeiro argumento (o índice), portanto, apenas a linha é impressa.
Você pode usar o mesmo comando para imprimir a cada quarta linha, começando na linha 1, 2 ou 3, mas você precisará acrescentar 3, 2 ou 1 linhas input
antes de alimentá-lo mapfile
, o que eu acho que é mais problemático do que vale a pena .
Isso também funciona:
mapfile -t lines < input
printf "%s%.0s%.0s%.0s\n" "${lines[@]}"
Aqui, printf
consome quatro entradas da matriz lines
por vez, apenas imprimindo a primeira e pulando as outras três %.0s
. Eu não gosto disso, já que você precisa mexer manualmente com a string de formato para diferentes intervalos ou pontos de partida.
sed -n '1~4p'