Donc, en général, j'ai tendance à rechercher le sedtraitement de texte - en particulier pour les gros fichiers - et à éviter généralement de faire ce genre de choses dans le shell lui-même.
Je pense cependant que cela pourrait changer. Je fouinais man kshet j'ai remarqué ceci:
<#pattern Seeks forward to the beginning of the
next line containing pattern.
<##pattern The same as <# except that the por‐
tion of the file that is skipped is
copied to standard output.
Sceptique quant à son utilité dans le monde réel, j'ai décidé de l'essayer. J'ai fait:
seq -s'foo bar
' 1000000 >file
... pour un million de lignes de données qui ressemblent à:
1foo bar
...
999999foo bar
1000000
... et l'a opposé sedcomme:
p='^[^0-8]99999.*bar'
for c in "sed '/$p/q'" "ksh -c ':<##@(~(E)$p)'"
do </tmp/file eval "time ( $c )"
done | wc -l
Ainsi, les deux commandes doivent obtenir jusqu'à 999999foo bar et leur implémentation de correspondance de modèle doit évaluer au moins le début et la fin de chaque ligne pour ce faire. Ils doivent également vérifier le premier caractère par rapport à un modèle annulé. C'est une chose simple, mais ... Les résultats n'étaient pas ce à quoi je m'attendais:
( sed '/^[^0-8]99999.*bar/q' ) \
0.40s user 0.01s system 99% cpu 0.419 total
( ksh -c ':<##@(~(E)^[^0-8]99999.*bar)' ) \
0.02s user 0.01s system 91% cpu 0.033 total
1999997
kshutilise ERE ici et sedun BRE. J'ai fait la même chose avec kshun motif de coque auparavant, mais les résultats ne différaient pas.
Quoi qu'il en soit, c'est un écart assez important - kshsurpasse sed10 fois. J'ai lu auparavant que David Korn a écrit son propre io lib et l'implémente dans ksh- peut-être que cela est lié? - mais je n'en sais presque rien. Comment se fait-il que la coquille le fasse si bien?
Encore plus étonnant pour moi, c'est que kshcela laisse vraiment son décalage là où vous le demandez. Pour obtenir (presque) la même chose de (GNU), sed vous devez utiliser -u- très lentement .
Voici un test grepv ksh:
1000000 #grep + head
( grep -qm1 '^[^0-8]99999.*bar'; head -n1; ) \
0.02s user 0.00s system 90% cpu 0.026 total
999999foo bar #ksh + head
( ksh -c ':<#@(~(E)^[^0-8]99999.*bar)'; head -n1; ) \
0.02s user 0.00s system 73% cpu 0.023 total
kshbat grepici - mais pas toujours - ils sont à peu près liés. Pourtant, c'est assez excellent, et ksh fournit une entrée anticipée - headcommence avant son match.
Cela semble trop beau pour être vrai, je suppose. Que font ces commandes différemment sous le capot?
Oh, et apparemment il n'y a même pas de sous-shell ici:
ksh -c 'printf %.5s "${<file;}"'
patternune expression régulière ou un modèle de coque plus simple?