Je souhaite imprimer les lignes impairs numérotées et numérotées à partir de fichiers.
J'ai trouvé ce script shell qui utilise Echo.
#!/bin/bash
# Write a Shell script that, given a file name as the argument will write
# the even numbered line to a file with name evenfile and odd numbered lines
# in a text file called oddfile.
# -------------------------------------------------------------------------
# Copyright (c) 2001 nixCraft project <http://cyberciti.biz/fb/>
# This script is licensed under GNU GPL version 2.0 or above
# -------------------------------------------------------------------------
# This script is part of nixCraft Shell script collection (NSSC)
# Visit http://bash.cyberciti.biz/ for more information.
# -------------------------------------------------------------------------
file=$1
counter=0
eout="evenfile.$$" # even file name
oout="oddfile.$$" # odd file name
if [ $# -eq 0 ]
then
echo "$(basename $0) file"
exit 1
fi
if [ ! -f $file ]
then
echo "$file not a file"
exit 2
fi
while read line
do
# find out odd or even line number
isEvenNo=$( expr $counter % 2 )
if [ $isEvenNo -ne 0 ]
then
# even match
echo $line >> $eout
else
# odd match
echo $line >> $oout
fi
# increase counter by 1
(( counter ++ ))
done < $file
echo "Even file - $eout"
echo "Odd file - $oout"
Mais n'est-il pas un moyen de le faire en une seule ligne?
Oui, utilisez awk, j'ai lu.
Lignes même numérotées:
awk 'NR % 2' filename
lignes impaires:
awk 'NR % 2 == 1' filename
Mais ça ne marche pas pour moi. Les deux produisent la même sortie, selon DIFF. Par rapport au fichier d'origine, ils sont à la fois la moitié aussi longue, et ils contiennent tous deux les lignes impairées. Est-ce que je fais quelque chose de mal?
Comme vous avez demandé "en une ligne":
awk '{print>sprintf("%sfile.%d",NR%2?"odd":"even",PROCINFO["pid"])}' filename
Notez que la majeure partie du code est due à votre choix de nom de fichier de sortie de sortie. Sinon, le code suivant suffirait à mettre des lignes impaires dans "Line-1" et même des lignes dans "Line-0":
awk '{print>"line-"NR%2}' filename
Je préfère être compatible Posix, dans la mesure du possible, je pensais que je postirais cette méthode alternative. Je les utilise souvent pour mangler du texte avant xargs
pipelines.
sed -n 'n;p'
sed -n 'p;n'
Bien que j'utilise souvent awk
, il est surchargé pour ce type de tâche.
Pour même des chiffres, le code devrait être
awk 'NR%2==0' filename
et pour les nombres impairs
awk 'NR%2==1' filename
Vous pouvez le faire avec une seule invocation sed
, aucun besoin de lire deux fois le fichier:
sed '$!n
w even
d' infile > odd
ou, si vous préférez en une ligne:
sed -e '$!n' -e 'w even' -e d infile > odd
Notez que ceux-ci ne donneront pas le résultat attendu si un fichier ne contient qu'une seule ligne (la ligne sera w
Ritten to even
au lieu de odd
comme le premier n
n'est pas exécuté). Pour éviter cela, ajoutez une condition:
sed -e '$!n' -e '1!{w even' -e 'd}' infile > odd
Comment ça fonctionne ? Eh bien, il utilise trois commandes sed
:
[.____] n
- sinon sur la dernière ligne Imprimer L'espace motif à stdout
(qui est redirigé vers le fichier odd
), Remplacez-le par la ligne suivante (maintenant, il traite une ligne pair) et continuez à exécuter les commandes restantes.
[.____] w
- Ajoutez l'espace de motif au fichier even
[.____] d
- Supprimer l'espace de modèle actuel et redémarrez le cycle - l'effet secondaire de ceci est que sed
n'imprimera jamais l'espace motif car il n'atteint jamais la fin du script
En d'autres termes, n
est exécuté uniquement sur des lignes impaires et w
et d
sont exécutés uniquement sur des lignes même. sed
_ N'arrive jamais à autopret à moins que je dise, comme je l'ai dit, l'entrée consiste en une seule ligne.
J'irais avec Perl
parce que j'aime Perl
:
Perl -pe 'BEGIN{open($e,">even_lines");open($o,">odd_lines")} $. % 2 ?select $o:select $e;'
Utilise le fait que -p
Imprime implicitement, reproduire comment sed
fonctionne - et nous utilisons select
pour choisir la poignée de fichier auquel elle écrit.
Essaye ça:
awk '{if(NR%2){print $0 > "odd.file"}else{print $0 > "even.file"}}' filename