Imaginez une sortie d'une commande comme
44444
55555
11111
22222
33333
comment puis-je extraire les N premières lignes (les deux premières dans l'exemple ci-dessus) et les ajouter à la fin, mais sans utiliser le fichier temporaire (donc en utilisant uniquement des tuyaux)?
11111
22222
33333
44444
55555
Quelque chose dans le sens de | sed -n '3,5p;1,2p'
(qui ne fonctionne évidemment pas car sed ne se soucie pas de l'ordre des commandes).
command-line
text-processing
Peter Uhnak
la source
la source
Réponses:
Copiez simplement ces lignes dans le tampon de maintien (puis supprimez-les) et lorsque sur la dernière ligne, ajoutez le contenu du tampon de maintien à l'espace de motif:
Avec
gnu sed
vous pourriez l'écrire commeVoici une autre façon avec ol '
ed
(ilr
lit la sortie desome command
dans le tampon de texte puism
ovule les lignes1,NUMBER
après la dernière$
):Notez que - comme indiqué - ces deux échoueront si la sortie a moins de
NUMBER
+1 lignes. Une approche plus solide serait (gnu sed
syntaxe):celui-ci ne supprime que les lignes de cette plage tant qu'elles ne sont pas la dernière ligne (
$!d
) - sinon, il écrase l'espace de motif avec le contenu du tampon de maintien (g
), puis seq
ferme (après avoir imprimé l'espace de motif actuel).la source
sed -e '1,NUMBER{H;1h;d;}' -e '$G'
fonctionne également de manière portative (notez que certainessed
implémentations ne peuvent pas contenir plus de quelques kilo-octets dans l'espace d'attente, donc NUMBER ne peut pas être trop grand là-bas)sed -e '1,NUMBER{H;1h;d' -e'}' -e '$G'
?-e
remplace une nouvelle ligne.d;}
n'est pas encore POSIX mais portable. Cela sera corrigé dans la prochaine spécification POSIX. Voir austingroupbugs.net/view.php?id=944#c27201,NUMBER{H;1h;d;}
n'est pas d'avoir un point-virgule immédiatement après l' accolade d' ouverture . Cela pourrait simplement être un bogue dans SunOS 4.1sed
dont la solution de contournement est toujours câblée dans mes doigts 20 ans plus tard, cependant.Une
awk
approche:Un avantage par rapport à l'
sed
approche de @ don_crissti est qu'il fonctionne toujours (sort les lignes) si la sortie a desn
lignes ou moins.la source
\n
en dur par ORS, afin que cela fonctionne avec d'autres séparateurs d'enregistrement (par exemple, vous voulez utiliser des paragraphes, etc.).J'ai
xclip
et avec cela cela peut être fait de cette façon:Voici sa description:
la source
Une façon Perl:
Ou, la même chose écrite moins cryptiquement:
Par exemple:
Explication
-ne
: lire le fichier d'entrée / flux ligne par ligne et appliquer le script donné par-e
à chaque ligne.$.<3
:$.
est le numéro de ligne actuel, changez3
donc le nombre de lignes que vous souhaitez déplacer.$.<3?($f.=$_):print;
: c'est l'opérateur conditionnel, le format général estcondition ? case1 : case2
, il s'exécuteracase1
sicondition
est vrai etcase2
s'il est faux. Ici, si le numéro de ligne actuel est inférieur à 3, il ajoute la ligne actuelle ($_
) à la variable$f
et, si le numéro de ligne est supérieur à 3, il s'imprime.}{ print $f
: le}{
raccourci est perl pourEND{}
. Il s'exécutera une fois que toutes les lignes d'entrée auront été traitées. À ce stade, nous aurons collecté toutes les lignes que nous voulons déplacer et nous aurons imprimé toutes celles que nous voulons laisser seules, alors imprimez les lignes enregistrées sous$f
.la source
perl -ne '$.<3?$f.=$_:print}{print $f
Utilisez POSIX
ex
. Oui, il est destiné à l'édition de fichiers, mais cela fonctionnera dans un pipeline.Cela peut avoir des commandes arbitraires ajoutées au début ou à la fin du pipeline et fonctionnera de la même manière. Mieux encore, étant donné la présence de
/dev/stdin
, il est compatible POSIX.(Je ne sais pas si
/dev/stdin
est spécifié dans POSIX ou non, mais je vois qu'il est présent à la fois sous Linux et Mac OS X.)Cela présente un avantage de lisibilité par rapport à l'utilisation
sed
de l'espace d'attente de - vous dites simplementex
«déplacez ces lignes jusqu'à la fin» et cela se fait. (Le reste des commandes signifie "imprimer le tampon" et "quitter", qui sont également assez lisibles.)NB: La
ex
commande donnée ci-dessus échouera si elle contient moins de 2 lignes en entrée.Lectures complémentaires:
la source
Un court
python
extrait:Passez le nom de fichier comme premier argument et le nombre de lignes à déplacer comme deuxième argument.
Exemple:
la source
Si vous pouvez stocker la sortie entière en mémoire:
la source
Voici une autre option qui nécessite GNU
sed
:-u
rend GNU sanssed
tampon pour que lased
commande ne consomme pas plus de 3 lignes de STDIN. La substitution de commande supprime les lignes vides, de sorte que la commande n'inclut pas les lignes vides à la fin de la sortie si les troisième, troisième et deuxième, ou troisième, deuxième et première lignes sont vides.Vous pouvez également faire quelque chose comme ceci:
Sans
sponge /dev/stdout|
la commande échouerait avec de longues entrées.sponge /dev/stdout
peut également être remplacé partac|tac
, même si cela s'imprime par exemplea\ncb
si l'entrée esta\nb\nc
où se\n
trouve un saut de ligne, ou avec(x=$(cat);printf %s\\n "$x")
, même si cela supprime les lignes vides de la fin de l'entrée. La commande ci-dessus supprime la première ligne lorsque le nombre de lignes de l'entrée est un ou deux.la source