Suponga que un directorio tiene 100 archivos que comienzan con la letra 'a'.
Si hago una grep <some string> a*
desde la terminal, ¿cómo manejará esto el shell?
¿Expandirá la expresión regular, obtendrá una lista de todos los archivos comenzando con a y grep en cada uno de ellos secuencialmente? ¿O hay alguna otra manera?
Suponga que tengo una matriz de los nombres de archivo anteriores que comienzan con 'a'. ¿Tomará más / menos tiempo si escribo un bucle for y hago la iteración yo mismo en un script de shell o un programa ac?
glob
expresión regular. Gran diferencia.Respuestas:
Primero, un nitpick: una cadena como
a*
en la sintaxis de shell normal es un glob, que funciona de manera diferente a las expresiones regulares.En una descripción general de alto nivel, el intérprete de shell (es decir, bash) expande la cadena
a*
a una lista de cada nombre de archivo que coincida con el patróna*
. Estos luego se convierten en parte de los parámetros de la línea de comandos para una sola instancia degrep
(para los programadores, todas las palabras expandidas van como cadenas separadas en elargv
argumento demain
). Esegrep
comando único analiza los argumentos de la forma que elija, y depende degrep
interpretar esos argumentos como nombres de archivo, opciones, argumentos de opción, expresiones regulares, etc., y tomar las acciones apropiadas. Todo ocurre secuencialmente (AFAIK ningunagrep
implementación usa múltiples hilos).Si implementa un bucle en un script de shell para hacer lo mismo, es casi seguro que será más lento que el proceso anterior, por las siguientes razones. Si genera un nuevo proceso grep para cada archivo, seguramente será más lento debido a la sobrecarga de la creación del proceso que se multiplica innecesariamente. Si construyó la lista de argumentos usted mismo en el script de shell y utilizó una sola instancia de
grep
, todo lo que haga en shell seguirá siendo más lento porque los comandos de shell deben interpretarse (por bash), lo que agrega una capa adicional de código, y obtendrá simplemente vuelva a implementar lo que bash ya hacía más rápido internamente en el código compilado.En cuanto a escribirlo usted mismo en C, probablemente pueda obtener fácilmente un rendimiento comparable al proceso descrito en el primer párrafo, pero es poco probable que pueda lograr una ganancia de rendimiento suficiente sobre las implementaciones grep / bash actuales para justificar el tiempo gastado sin profundizar en optimizaciones de rendimiento específicas de la máquina o sacrificar la portabilidad. Tal vez podría intentar crear una versión paralelizable arbitrariamente
grep
, pero incluso eso puede no ayudar, ya que es más probable que esté vinculado a E / S que a CPU. La expansión global y el grep ya son "lo suficientemente rápidos" para la mayoría de los propósitos "normales".fuente
zcat
yzgrep
; no es necesario descomprimirlos uno por unoSí, se expandirá a una lista de archivos y alimentará la lista resultante al
grep
programa. Al menos eso es lo queman bash
dice en la subsección Pathname Expansion .Hay otra forma de usar la expansión en casos simples como usted menciona: escriba
grep <some_string> a
y antes de presionar*
, presione ESC. Esto expandirá la lista de archivos coincidentes directamente en la línea de comando, para que pueda verificar que la lista esté bien antes de presionar Enter.En cuanto a la segunda parte de su pregunta, depende. Si quiere escribir un bucle for que ejecute grep en cada uno de los archivos, entonces definitivamente sería más lento, porque el programa grep se ejecutará no una vez, sino una vez por archivo. Sin embargo, lo que es importante tener en cuenta es que hay un cierto límite en la longitud expandida de los argumentos de la línea de comandos que puede usar, aunque generalmente es bastante alto. Para ver eso, puedes intentarlo
grep adasdsadf /usr/*/*/* >/dev/null
.fuente
ESC+*
no es exactamente lo mismo que dejar que bash se expanda * porqueESC+*
insertará archivos de puntos (nombres que comienzan con a.
) mientras que la expansión de*
depende de ladotglob
shopt
configuración. La secuencia de teclas para expandir e insertar globos esC-x *
por defecto y se asigna al comando readlineglob-expand-word
.a*
expansión, pero ciertamente es importante en un ámbito más amplio.zsh
nota: simplemente presionando la tecla de tabulación en los parámetros expandibles (patrones globales, expansión de llaves, sustitución de comandos, ...) los expandirá.C-x
acceso directo y no expande la lista de archivos en mi sistema (usando bash).C-x *
solo hace globos que solo hacen nombres de archivo, pero enEsc *
realidad hace mucho más, ya que esinsert-completions
, como en todas las terminaciones posibles. Esto significa que el usoEsc *
en una línea de comando vacía insertará el nombre de cada archivo ejecutable en su$PATH
, por ejemplo.