Por lo tanto, en general, tiendo a buscar el sed
procesamiento de texto, especialmente para archivos grandes, y generalmente evito hacer ese tipo de cosas en el shell.
Sin embargo, creo que eso puede cambiar. Estaba hurgando man ksh
y noté esto:
<#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.
Escéptico de la utilidad del mundo real, decidí probarlo. Yo hice:
seq -s'foo bar
' 1000000 >file
... para un millón de líneas de datos que se parecen a:
1foo bar
...
999999foo bar
1000000
... y lo enfrenté sed
como:
p='^[^0-8]99999.*bar'
for c in "sed '/$p/q'" "ksh -c ':<##@(~(E)$p)'"
do </tmp/file eval "time ( $c )"
done | wc -l
Por lo tanto, ambos comandos deben llegar hasta 999999foo bar y su implementación de coincidencia de patrones debe evaluar al menos el comienzo y el final de cada línea para hacerlo. También tienen que verificar el primer carácter contra un patrón negado. Esto es algo simple, pero ... Los resultados no fueron lo que esperaba:
( 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
ksh
usa ERE aquí y sed
un BRE. Hice lo mismo con ksh
un patrón de shell antes, pero los resultados no fueron diferentes.
De todos modos, esa es una discrepancia bastante significativa: ksh
supera sed
10 veces más. He leído antes que David Korn escribió su propia io lib y la implementa, ksh
¿posiblemente esto esté relacionado? - Pero no sé casi nada al respecto. ¿Cómo es que el shell hace esto tan bien?
Aún más sorprendente para mí es que ksh
realmente deja su desplazamiento justo donde lo preguntas. Para obtener (casi) lo mismo de (GNU) sed
tiene que usar -u
, muy lento .
Aquí hay una prueba grep
v.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
ksh
late grep
aquí, pero no siempre, están bastante empatados. Aún así, eso es bastante excelente y ksh
proporciona información anticipada: head
la entrada comienza antes de su coincidencia.
Parece demasiado bueno para ser verdad, supongo. ¿Qué hacen estos comandos de manera diferente bajo el capó?
Ah, y al parecer, ni siquiera hay una subshell aquí:
ksh -c 'printf %.5s "${<file;}"'
pattern
una expresión regular o un patrón de shell más simple?