UNIX команды foreach и sed!

Это возможно, если CONFIG_BLOCK не определено, поскольку init / do_mounts.c содержится в mount_root , который запускается после сбоя ядра / init в initramfs следующее:

#ifdef CONFIG_BLOCK
    {
        int err = create_dev("/dev/root", ROOT_DEV);

        if (err < 0)
            pr_emerg("Failed to create /dev/root: %d\n", err);
        mount_block_root("/dev/root", root_mountflags);
    }
#endif

Источник: https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/init/do_mounts. c? id = c69e3c3a0c014e86750e78b7e2ae823f7a9b2cb2 # n535

В этом случае mount_root завершается успешно, ничего не сделав, и ядро ​​продолжает рассматривать initramf как надлежащий корневой файловый сервер.

К сожалению, отключение CONFIG_BLOCK в большинстве случаев нецелесообразно. Что заставило меня поверить, что это должно сработать, так это то, что в патче для конкретной платы разработки, с которой я работаю, условие было заменено на:

#if defined(CONFIG_BLOCK) && !defined(CONFIG_INITRAMFS_SOURCE)

Было бы неплохо добавить поддержку root = initramfs , который заставляет mount_root возвращаться без каких-либо действий, и это должен быть тривиальный однострочный патч. Однако я понятия не имею, будет ли это приемлемо для апстрима.

0
24.02.2018, 22:47
2 ответа

Debajo de uno está el que probé

filnames.txt==> Contiene todos los nombres de archivo

 for j in `cat filenames.txt`; do sed "s/,/NA/g" $j >newfiles_$i;i=$(($i + 1)); done
0
28.01.2020, 02:43

Supongo que sus archivos CSV no tienen estrictamente comillas con comas y que no contienen campos con saltos de línea.

Esto cambiará los campos vacíos o campos que contienen solo espacios aNA:

awk 'BEGIN { FS=OFS="," } { for (i=1;i<=NF;++i) if ($i ~ /^ *$/) $i = "NA"; print }'

Para cada campo separado por comas -en cada línea de entrada, probamos si coincide con la expresión regular ^ *$. Si es así, el campo se reemplaza por la cadena NA. Las variables FSy OFSen el bloque BEGINson ​​los separadores de campo de entrada y salida, respectivamente. NFes el número de campos que awkdetecta en la línea de entrada actual y si ies un número entero, $iserá el campo correspondiente a ese número entero, contando desde uno.

Su línea de ejemplo,

SMVV, 2015-01-01 00:00,50065,780,7,1000,-2,18,,,1000

se convertiría en

SMVV, 2015-01-01 00:00,50065,780,7,1000,-2,18,NA,NA,1000

Ahora, para ejecutar esto en todos sus archivos, asumo que todos están en un directorio llamado diry que los nombres de los archivos coinciden con el patrón SMVV50065*.csv.

Pasar por encima de estos archivos es una cuestión de

for name in dir/SMVV50065*.csv; do
    test -f "$name" || continue
    # construct new name and call awk here
done

Probamos con test -fsi el $namees realmente un archivo normal y omitimos el resto de la iteración si no lo es. No sería si el patrón coincide con ningún nombre de directorio, o si el patrón no coincide con nada (, en cuyo caso se dejará sin expandir ).

Para construir nuevos nombres de archivo en el patrón que sugiere,podemos mantener una variable de contador que se incrementa en cada iteración, desde una en adelante, y llamar printfcon una cadena de formato que da el nombre del archivo de salida usando esta variable:

i=1
for name in dir/SMVV50065*.csv; do
    test -f "$name" || continue

    newname=$( printf 'newfile%02d.csv' "$i" )
    i=$(( i + 1 ))

    # call awk here
done

El %02den el formato printfnos da un entero de 2 -dígitos cero -de $i.

Ahora solo es cuestión de llamar awkal nombre de archivo anterior y escribir el resultado en el nuevo. Escribiremos el resultado en archivos en el directorio result, solo para mantenerlos separados de los archivos originales.

#!/bin/sh

mkdir -p result

i=1
for name in dir/SMVV50065*.csv; do
    test -f "$name" || continue

    newname=$( printf 'newfile%02d.csv' "$i" )
    i=$(( i + 1 ))

    awk 'BEGIN { FS=OFS="," } { for (i=1;i<=NF;++i) if ($i ~ /^ *$/) $i = "NA"; print }' "$name" >result/"$newname"
done

Lo único que he hecho aquí es asegurarme de que el directorio resultrealmente existe con mkdir -p resultal principio. También agregué una línea#!-en la parte superior para decir que este es un script sh.

Y de nuevo, con un poco de diagnóstico y parametrización añadidos:

#!/bin/sh

indir=dir
outdir=result

mkdir -p "$outdir"

i=1
for name in "$indir"/SMVV50065*.csv; do
    if [ ! -f "$name" ]; then
        printf 'Not a regular file: "%s"\n' "$name" >&2
        continue
    fi

    newname=$( printf '%s/newfile%02d.csv' "$outdir" "$i" )
    i=$(( i + 1 ))

    printf 'Processing "%s" into "%s"...\n' "$name" "$newname" >&2

    awk 'BEGIN { FS=OFS="," } { for (i=1;i<=NF;++i) if ($i ~ /^ *$/) $i = "NA"; print }' "$name" >"$newname"
done

Obviamente, podrías poner tu sedcomando aquí en lugar de mi awkcosita, si quieres.


Pregunta en comentarios:

Lo anterior parece difícil, ¿por qué no podemos simplemente hacer

foreach file (ls SMVV50065-2015-0[1-7].csv)
    sed 's/,/NA/g' > newfile0[1-7].csv
end 

Responder:

Primero tenemos que empezar usando la sintaxis correcta. Esto se parece un poco a la sintaxis del shell csh, pero dado que no se mencionó ningún shell en particular en la pregunta y dado quesh-los shells similares se usan más comúnmente, y ya que personalmente tengo muy poca experiencia con cshy tcsh, voy a convertirlo en sintaxis sh.

El bucle en shshells es foren lugar de foreachy usamos iny doen lugar del paréntesis. También sugiere usar lspara el ciclo, pero lses estrictamente un comando interactivo cuyo resultado es solo para mirar(ver " Por qué *no *analizar `ls `? " ). Es suficiente con un patrón de globbing de nombre de archivo para generar una lista de nombres de archivo para recorrer.

Así que usemos su bucle con la sintaxis correcta:

for file in SMVV50065-2015-0[1-7].csv; do
    sed 's/,/NA/g' > newfile0[1-7].csv
done

El siguiente problema con el bucle aquí es que no sabemos si $fileserá un valor útil. Si el patrón SMVV50065-2015-0[1-7].csvcoincide con un nombre de directorio o si no coincide con nada, entonces no deberíamos usar $file, así que probemos eso:

for file in SMVV50065-2015-0[1-7].csv; do
    test -f "$file" || continue

    sed 's/,/NA/g' > newfile0[1-7].csv
done

Ahora para la invocación sed:Deberá pasar el nombre de archivo $filea sedpara que tenga algo en lo que trabajar:

for file in SMVV50065-2015-0[1-7].csv; do
    test -f "$file" || continue

    sed 's/,/NA/g' "$file" > newfile0[1-7].csv
done

El siguiente problema es que en realidad no puede redirigir la salida de seda un patrón de englobamiento de nombre de archivo como newfile0[1-7].csv. El shell expandirá un patrón global a todos los nombres que coincidan con ese patrón, o permanecerá sin expandir si no coincide con nada.

Suponiendo que no tiene ningún archivo en el directorio actual que coincida con el patrón newfile0[1-7].csv. Luego, el ciclo creará un archivo llamado newfile0[1-7].csv, y este relleno se sobrescribirá en cada iteración del ciclo.

Es por eso que introduje mi variable i, para poder construir un nuevo nombre de archivo en cada iteración:

i=1
for file in SMVV50065-2015-0[1-7].csv; do
    test -f "$file" || continue

    sed 's/,/NA/g' "$file" >"newfile0$i.csv"
    i=$(( i + 1 ))
done

Supuse que puede tener mucho más que solo siete archivos para procesar, y es por eso que pasé por ese pequeño problema adicional para generar el nombre del archivo de salida usando printf, para asegurarme de que obtuviéramos un nombre de archivo con un cero -número rellenado en él.

El ciclo anterior puede funcionar para usted tal como está, pero si lo reformulo un poco (asigne el nuevo nombre de archivo a una variable y utilícelo consed):

i=1
for file in SMVV50065-2015-0[1-7].csv; do
    test -f "$file" || continue

    newname="newfile0$i.csv"
    i=$(( i + 1 ))

    sed 's/,/NA/g' "$file" >"$newfile"
done

¿Ves? Estamos más o menos de vuelta en mi solución (sin las campanas y silbidos adicionales de mi última variación ). La única diferencia radical es que aquí asume que todos los archivos estarán disponibles en el directorio actual y que los archivos de salida deben crearse junto con los archivos originales.

1
28.01.2020, 02:43

Теги

Похожие вопросы