scripts script programas pasar parametros operaciones manejo else ejemplos cadenas aritmeticas bash for-loop nested-loops paste

script - Recorriendo pares de valores en bash



script linux ejemplos (5)

Estoy de acuerdo con la respuesta propuesta actualmente por fedorqui en el contexto de la pregunta que se hace actualmente. Lo siguiente se proporciona solo para proporcionar algunas respuestas más generales.

Un enfoque más general (para bash 4.0 o más reciente) es almacenar sus pares en una matriz asociativa:

declare -A pairs=( [4_1]=4_2 [5_1]=5_2 [6_1]=6_2 [7_1]=7_2 [8_1]=8_2 ) for i in "${!pairs[@]}"; do j=${pairs[$i]} paste "$i.txt" "$j.txt" >"${i}.${j}.txt" done

Otro (compatible con versiones anteriores de bash) es usar más de una matriz convencional:

is=( 4_1 5_1 6_1 7_1 8_1 ) js=( 4_2 5_2 6_2 7_2 8_2 ) for idx in "${!is[@]}"; do i=${is[$idx]} j=${js[$idx]} paste "$i.txt" "$j.txt" >"$i.$j.txt" done

Tengo 10 archivos de texto y quiero paste cada archivo con su par, de modo que tengo un total de 5 archivos.

Intenté lo siguiente:

for i in 4_1 5_1 6_1 7_1 8_1 do for j in 4_2 5_2 6_2 7_2 8_2 do paste ${i}.txt ${j}.txt > ${i}.${j}.txt done done

Sin embargo, este código combina todas las combinaciones posibles en lugar de solo combinar los pares coincidentes.

Entonces, me gustaría que el archivo 4_1.txt se 4_2.txt con 4_2.txt , 5_1.txt con 5_2.txt , etc.


Hay un patrón común en el que tiene pares de archivos, donde un nombre del par puede derivarse fácilmente del otro. Si el archivo del que conoce el nombre es X y el otro archivo es Y, tiene los siguientes casos de uso comunes.

  • Para renombrar, Y es X con una extensión eliminada y / o un sello de fecha agregado.
  • Para la transcodificación, Y es X con una extensión diferente y quizás un directorio diferente.
  • Para muchas tareas de análisis de datos, X e Y comparten algunas partes del nombre del archivo, pero tienen diferentes parámetros o extensiones.

Todos estos se prestan al mismo esqueleto de código aproximado.

for x in path/to/base*.ext; do dir=${x%/*} # Trim trailing file name, keep dir base=${x##*/} # Trim any leading directory # In this case, $y has a different subdirectory and a different extension y=${dir%/to}/from/${base%.ext}.newext # Maybe check if y exists? Or doesn''t exist? if [ -e "$y" ]; then echo "$0: $y already exists -- skipping" >&2 continue fi mv or ffmpeg or awk or whatever "$x" and "$y" done

La clave aquí es la observación de que y puede derivarse de x con algunas sustituciones de variables simples. Entonces, recorre los valores x y calcula el valor y correspondiente dentro del ciclo.

Aquí, hemos utilizado los operadores incorporados ${variable#prefix} y ${variable%suffix} del shell para devolver el valor de la variable con cualquier prefix inicial o suffix final, respectivamente, recortados. (También hay ## y %% para que coincida con la coincidencia más larga posible, en lugar de la más corta posible. La expresión después de # o % es un patrón de globo de caparazón regular). Por lo general, esto debería ser todo lo que necesita, aunque con frecuencia ve sed o guiones awk incluso para este trabajo trivial (donde realmente debería intentar evitar un proceso externo), así como, por supuesto, para transformaciones más exigentes.

Si necesita recorrer los archivos x dispersos en diferentes directorios, tal vez el ciclo debería comenzar con algo como

find dir1 dir2 etc/and/so/forth -type f -name ''x-files*.ext'' -print | while IFS='''' read -r x; do :

Un problema comúnmente visto en preguntas similares son las respuestas que no pueden citar $x y $y correctamente. En general, cualquier variable que contenga un nombre de archivo siempre debe estar entre comillas dobles.

Donde X e Y no están relacionados, una solución común es recorrer un documento aquí que contiene la asignación:

while read -r x y; do : stuff with "$x" and "$y" done <<''____HERE'' first_x_value first_y_value another_x corresponding_y random surprise ____HERE


Puede usar una matriz asociativa:

animals=(dog cat mouse) declare -A size=( [dog]=big [cat]=medium [mouse]=small ) declare -A sound=( [dog]=barks [cat]=purrs [mouse]=cheeps ) for animal in "${animals[@]}"; do echo "$animal is ${size[$animal]} and it ${sound[$animal]}" done

Esto le permite atravesar pares, triples, etc. Créditos: la idea original está tomada de la respuesta de @ CharlesDuffy.


Si desea usar una variable y realizar una acción con ella, solo necesita usar un bucle:

for file in 4 5 6 7 8 do paste "${file}_1" "${file}_2" done

Esto lo hara

paste 4_1 4_2 paste 5_1 5_2 ...


lo anterior no funcionó para mí, pero lo siguiente sí lee valores en pares de una lista ordenada

(pueden ser más que pares agregando ''líneas de lectura'' adicionales :-)

while read x; do read y echo $x $y done << ''___HERE'' X1 Y1 X2 Y2 X3 Y3 ___HERE

produce

X1 Y1 X2 Y2 X3 Y3