Tengo una de 4 columnas del archivo CSV, por ejemplo:

0001 @ fish @ animal @ eats worms

Yo uso sed a hacer un buscar y reemplazar en el archivo, pero tengo que limitar este buscar y reemplazar sólo el texto se encuentra dentro de la columna 3.

¿Cómo puedo tener un buscar y reemplazar sólo se producen en esta columna?

  • Eso no es un CSV, pero asumo que está haciendo que nos sea más fácil de leer. Se garantiza que el delimitador entre los campos (que se muestra como @ en tu ejemplo) puede nunca aparecer en cualquier otra parte? Así que usted está preguntando cómo buscar un trozo de texto literal entre la segunda y la tercera ‘@’, o es más complejo, es decir, los patrones? Por favor, dar un ejemplo de lo que debe ser encontrado, y lo será reemplazado por.
  • Es un CSV, pero utiliza @ para dividir las columnas, con los espacios circundantes. Sólo he mostrado una única fila para mostrar el formato. Comas aparecen con frecuencia en todo el archivo, pero @ no aparece nunca, así que he utilizado @ como el divisor. Un ejemplo de sustitución es, sed -i "s/a/b/g" ./file.csv (reemplazar todas las apariciones de «a» con «b», excepto yo sólo quiero esta sustitución se producen en el interior de entradas que se encuentra en la columna 3, y para no afectar a los espacios a ambos lados de @.
InformationsquelleAutor Village | 2012-04-07

3 Comentarios

  1. 4

    Son usted seguro de que quiere ser el uso de sed? ¿Qué acerca de csvfix? Es el archivo CSV agradable y sencillo ya que no hay citas o incrustado comas u otros personajes malvados que hacen de expresiones regulares…a menos que satisfactorio manera de tratar con un general archivo CSV? Estoy suponiendo que el @ es la ‘coma’ en su formato.

    Considerar el uso de awk en lugar de sed:

    awk -[email protected] '$3 ~ /pattern/{ OFS= "@"; $3 = "replace"; }'

    Posiblemente, usted debe tener un bloque BEGIN que establece la OFS una vez. Para una línea de entrada, no tenía ningún probabilidades (y que probablemente estaría en apuros para medir una diferencia de un millón de líneas de entrada, también):

    $ echo "pattern @ pattern @ pattern @ pattern" | 
    > awk -[email protected] '$3 ~ /pattern/{ OFS= "@"; $3 = "replace"; }'
    pattern @ pattern @[email protected] pattern
    $

    Si sed todavía parece atractiva, entonces:

    sed '/^\([^@]*@[^@]*\)@[email protected]\(.*\)/s//@[email protected]/'

    Por ejemplo (y la nota ligeramente diferentes de entrada y de salida se puede fijar a la manija de la misma como la awk bastante fácilmente si es necesario):

    $ echo "[email protected]@[email protected]" |
    > sed '/^\([^@]*@[^@]*\)@[email protected]\(.*\)/s//@[email protected]/'
    [email protected]@[email protected]
    $

    La primera expresión regular busca el comienzo de una línea, un campo de no-a-la-signos, un signo, otro campo de la no-en-signos y recuerda el lote; se ve un signo, el patrón (que debe ser en el tercer campo ya que los dos primeros campos se ha igualado ya), otro en el signo -, y, a continuación, el residuo de la línea. Cuando la línea de los partidos, entonces se reemplaza la línea con los dos primeros campos (sin cambios, según se requiera), luego se agrega el reemplazo de tercer campo, y el resto de la línea (sin cambios, según se requiera).

    Si usted necesita para editar en lugar de simplemente reemplazar el tercer campo, entonces usted piensa acerca del uso de awk o Perl o Python. Si usted todavía está restringida a sed, entonces usted explorar el uso de la bodega, espacio para llevar a cabo parte de la línea mientras se manipula la otra parte en el espacio en el patrón, y al final de la re-integración de su deseada de la línea de salida de la bodega, el espacio y el patrón de espacio antes de la impresión de la línea. Eso es casi tan complicado como suena, en realidad, posiblemente incluso más complicada de lo que parece. Me gustaría ir con Perl (porque aprendí hace mucho tiempo y hace este tipo de cosas con bastante facilidad), pero se puede usar cualquiera que nosed herramienta que le gusta.


    Perl de edición en el tercer campo. Tenga en cuenta que la salida por defecto es $_ que había que volver a montar en el auto-dividir los campos en la matriz @F.

    $ echo "[email protected]@[email protected]" | sh -x xxx.pl
    > perl -pa -[email protected] -e '$F[2] =~ s/\s*pat(\w\w)rn\s*/prefix-$1-suffix /; $_ = join "@", @F; ' "[email protected]"
    [email protected]@ prefix-te-suffix @pattern
    $

    Una explicación. El -p significa ‘bucle, la lectura de las líneas en $_ y la impresión $_ al final de cada iteración’. El -a significa » auto-split $_ en la matriz @F‘. El [email protected] significa el separador de campos es @. El -e es seguido por el programa Perl. Las matrices son indexadas desde 0 en Perl, por lo que el tercer campo se divide en $F[2] (el sigilo — el @ o $ — cambia dependiendo de si está trabajando con un valor de la matriz o de la matriz como un todo. El =~ es un operador de coincidencia, se aplica la expresión en el lado derecho para el valor en el lado izquierdo. El sustituto del patrón reconoce cero o más espacios \s* seguido por pat, a continuación, dos ‘palabra’ de los personajes que se recuerdan en $1, entonces rn y cero o más espacios de nuevo; tal vez no debería ser un ^ y $ allí enlazar con el inicio y el final del campo. La sustitución de un espacio, ‘prefijo’, el recordado par de letras, y ‘el sufijo’ y un espacio. El $_ = join "@", @F; vuelve a montar la línea de entrada $_ desde el posiblemente modificado distintos campos y, a continuación, el -p impresiones que fuera. No es tan limpio como me gustaría (por lo que probablemente hay una mejor manera de hacerlo), pero funciona. Y usted puede hacer arbitraria transforma arbitrarias de los campos en Perl sin mucha dificultad. Perl también tiene un módulo de Text::CSV (y una alta velocidad de la versión C, Text::CSV_XS) que puede manejar realmente complejo archivos CSV.

  2. 1

    Esencialmente romper la línea en tres piezas, con el modelo que usted está buscando en el medio. A continuación, mantener el exterior de las piezas y reemplazar el medio.

    /\([^@]*@[^@]*@\[^@]*\)pattern\([^@]*@.*\)/s//\1replacement\2/

    \([^@]*@[^@]*@\[^@]*\) – recoger todo antes de que el patrón, incluyendo la 3ª @ y cualquier texto antes de las matemáticas – esto se convierte en \1

    pattern – la cosa que usted está buscando

    \([^@]*@.*\) – se reúnen todo después de que el patrón – esto se convierte en \2

    A continuación, cambie la línea que en \1, a continuación, el replacement, entonces todo después de pattern, que es \2

  3. 1

    Esto podría funcionar para usted:

    echo 0001 @ fish @ animal @ eats worms|
    sed 's/@/&\n/2;s/@/\n&/3;h;s/\[email protected]*//;s/.*\n//;y/a/b/;G;s/\([^\n]*\)\n\([^\n]*\).*\n//'
    0001 @ fish @ bnimbl @ eats worms

    Explicación:

    1. Definir el campo que se va a trabajar (en este caso el 3) y insertar un salto de línea (\n) antes y después de ella. s/@/&\n/2;s/@/\n&/3
    2. Guardar la línea en la bodega del espacio. h
    3. Eliminar los campos de cada lado s/\[email protected]*//;s/.*\n//
    4. Ahora el proceso de campo, es decir, cambiar todos los a's a b's. y/a/b/
    5. Ahora anexar el original de la línea. G
    6. Sustituir el nuevo campo para el campo anterior (también la eliminación de cualquier saltos de línea). s/\([^\n]*\)\n\([^\n]*\).*\n/\2\1/

    N. B. Que en el paso 4 el espacio en el patrón sólo contiene el campo definido, por lo que cualquier número de comandos que puede ser llevado a cabo aquí y el resultado no va a afectar el resto de la línea.

Dejar respuesta

Please enter your comment!
Please enter your name here