LinuxForum.Fans
Тема

[Решено]сравнение массивов

Автор: prostornet 44 сообщений 8979 просмотров
#372362

Есть ряд массивов подобных такому


Вася Пупкин
234
10/01/2001
True
Ложь

Как не допустить неопределенности ?

#372397

"smaharbA" написал:
Как не допустить неопределенности ?
придумать однозначные правила преобразования типов. Как в php например.

Или вообще запретить любые преобразования, как в нормальных ЯП. IRL конечно "нормальные ЯП" со строгой типизацией значения не имеют(практического), и пользуются обычными ЯП, но нужно помнить, о том, что сладкое всё равно нет смысла сравнивать с солёным. Даже если ЯП это допускает. Сишачка/пхп допускают, и получается ерунда.

Потому и рекомендую юзать (( )), т.к. этот способ ГАРАНТИРОВАННО интерпретирует значение В ЧИСЛО, а не в хрен знает что.

ЗЫЖ кстати ТС не написал, какой он смысл вкладывает в элементы массивов. И т.к. в bash имеется всего два типа, то для ТСа есть два решения. ЛИБО одно, ЛИБО второе. Но не оба сразу. Потому-как переменная не может быть числом и строкой одновременно. Возможна только разная интерпретация.
#372485

Для нормального человека

2. Вася

всегда стоит впереди чем

12. Агафон

а вот для большинства сортировок в шелах и прочих лс наоборот (тока не надо учить всевозможным ls -v и прочим sort -n, они в самый раз делают почти то, что выше названо "код должен...")
(о неопределенности)

#372503
"smaharbA" написал:
2. Вася

всегда стоит впереди чем

12. Агафон

не всегда. А что такое 2/12? Если это порядковый номер, то почему не по порядку?

text
12 Агафон
26 Коля
2 Вася
14 Маша
13 Лиза
26 Лаура
17 Вася

что это за список, и с какого перепугу третью строчку надо заменить на первую? А что делать с остальными?

"smaharbA" написал:
тока не надо учить
а я и не буду. Вы необучаемы. Вам видимо не дано понять, что "строка" и "число", разные вещи. И что сортировки тоже разные бывают, одни строчки сортируют, другие числа, а третьи ещё что-то.
#372693
Vascom написал:
Вот так:
text
a=( 1 2 3 4 5 )
b=( 0 2 4 6 8 10 12 14 16 18 )

for ((k=0; k < 5 ; k++)) do for ((n=0; n < 10 ; n++)) do if [ ${a[$k]} -ne ${b[$n]} ] then echo "${a[$k]} ${b[$n]}" >> noteq_file else echo "${a[$k]} ${b[$n]}" >> eq_file fi done done

drBatty написал:
[quote="Vascom"]if [ ${a[$k]} -ne ${b[$n]} ]

правильнее

text
if [ "${a[$k]}" != "${b[$n]}" ]

[/quote]
это не совсем правильно, так как во втором файле я получаю вместо 8 результатов (несовпавших цифр) 48 результатов (задвоенных)

#372695

drBatty написал:
[quote="prostornet"]Подскажите пожалуйста как сравнить два массива и вывести совподающие элементы в один файл, а отличающиеся в другой.
в баше это через задницу. Вам точно нужно именно массивы, или пойдут строки в файле? Это задачка от HR (экзамен, с другом поспорили)?[/quote]

Нет это не задачка и не спор, посути это лень, я не хочу вводит пару команд и потом всматриваться в результаты и выискивать нужное. Хочется нажать кнопку [сделать красиво] и получить результат.
#372696

Ну ты задачу опиши получше, или сам переделай вывод в файл как тебе требуется. Это же лишь пример, показывающий как реализовать сравнение.

#372700

Вот именно это у меня и не получается, такой задвоенный вывод я и до этого получал.
А задачу я вроде с самого начала описал. Есть два массива с цифрами, сравниваем, в один файл цифры совпашие, а в другой те что не совпали, но все в единичном экземпляре.

#372703

Пример массивов и выходных файлов можешь дать?
"те что не совпали, но все в единичном экземпляре" - не понятно.

#372705

array_a = (2 3 6 9)
array _b = (1 2 3 4 5 6 7 8 9 10)

file_a: 2 3 6 9
file_b: 1 4 5 7 8 10

P.S.: без повторений как в цикле for for if и во втором файле получаем вывод: 1 3 4 5 6 7 8 9 10 (совпала 2 её не вывели) 1 2 4 5 6 7 8 9 10 (совпала 3 её не вывели) и т.д.

#372708

"prostornet" написал:
это не совсем правильно, так как во втором файле я получаю вместо 8 результатов (несовпавших цифр) 48 результатов (задвоенных)
man sort
man uniq

Если хотите конкретику, то данные покажите. Или читайте маны самостоятельно.

Третий вариант: денег заплатить кому-нить.
#372710

"prostornet" написал:
А задачу я вроде с самого начала описал. Есть два массива с цифрами, сравниваем, в один файл цифры совпашие, а в другой те что не совпали, но все в единичном экземпляре.
откуда вы массивы взяли?

ну сделайте третий массив, массив совпадений.

если совсем лень: http://us1.php.net/manual/ru/function.array-intersect.php
#372734

Подскажите тогда как реализовать цикл:

есть var1 я её сравниваю с var2, которая если не равна var1 мы её увеличиваем на 1 и опять проверяем.

Есть уже цикл while read line; do новый цикл описанный выше done < ${FILE}

#372737

prostornet,

text
#!/bin/bash

(( J_MAX = 5 ))

for (( J = 0; J < J_MAX; J++ )); do echo "J=$J" done

#372738

prostornet, вы мне надоели, с вас $5 за решение

text
#!/bin/bash

A=(2 3 6 9) B=(1 2 3 4 5 6 7 8 9 10)

echo "A: '${A[@]}', B: '${B[@]}'"

# intersect A B

MAX_INDEX_A=${#A[@]} MAX_INDEX_B=${#B[@]} for (( INDEX_A = 0; INDEX_A < MAX_INDEX_A; INDEX_A++ )); do for (( INDEX_B = 0; INDEX_B < MAX_INDEX_B; INDEX_B++ )); do if (( ${A[$INDEX_A]} == ${B[$INDEX_B]} )); then echo $INDEX_A $INDEX_B ${A[$INDEX_A]} fi done done

[console]A: '2 3 6 9', B: '1 2 3 4 5 6 7 8 9 10'
0 1 2
1 2 3
2 5 6
3 8 9[/console]

#372739
drBatty написал:
prostornet, вы мне надоели, с вас $5 за решение

[console]A: '2 3 6 9', B: '1 2 3 4 5 6 7 8 9 10'
0 1 2
1 2 3
2 5 6
3 8 9[/console]

Я не против пяти баксов, но такое решение (вывод только совпавших цифр в массиве A и B) у меня было готово сразу (только без вывода индекса ), о чем я уже писал.
А вот вывод несовпавших цифр (1 4 5 6 7 8 10) это как?
Если в Ваш скрипт добавить строки:

text

else 
     echo ${B[$INDEX_B]}

вот тут получается множественный вывод несовпавших цифр.
У меня был вопрос возможно ли это решить без sort и uniq, с помощью циклов?

#372741

"prostornet" написал:
вот тут получается множественный вывод несовпавших цифр.
тогда так:
text
#!/bin/bash

A=(2 3 6 9) B=(1 2 3 4 5 6 7 8 9 10)

echo "A: '${A[@]}', B: '${B[@]}'"

# intersect A B

LAST_NE="-1" # таких чисел не бывает

MAX_INDEX_A=${#A[@]} MAX_INDEX_B=${#B[@]} for (( INDEX_A = 0; INDEX_A < MAX_INDEX_A; INDEX_A++ )); do for (( INDEX_B = 0; INDEX_B < MAX_INDEX_B; INDEX_B++ )); do if (( ${A[$INDEX_A]} == ${B[$INDEX_B]} )); then echo + $INDEX_A $INDEX_B ${A[$INDEX_A]} else if (( LAST_NE != ${A[$INDEX_A]} )); then echo - $INDEX_A $INDEX_B ${A[$INDEX_A]} ${B[$INDEX_B]} LAST_NE=${A[$INDEX_A]} fi fi done done

"prostornet" написал:
У меня был вопрос возможно ли это решить без sort и uniq, с помощью циклов?
можно. Просто в нормальной жизни массивы просто так из ниоткуда не появляются как у вас.
#372755
drBatty написал:
можно. Просто в нормальной жизни массивы просто так из ниоткуда не появляются как у вас.

Вывод все равно не дает желаемого результата.


Хотел вот что (напримере вывода команды nmap -sP), показать все занятые и все свободные адреса)
./test.sh 192.168.1 :

text

#!/bin/bash

NET=$1

RED='\033[31m' BLUBG='\033[44m' NC='\033[0m'

TMP1=/tmp/ipchk1.tmp TMP2=/tmp/ipchk2.tmp

rm -f ${TMP1} rm -f ${TMP2}

/usr/bin/nmap -sP ${NET}.0/24 | sed -rn 's/.*[^0-9](([0-9]+\.){3})([0-9]+).*/\3/p' > ${TMP1}

b_ip=0 while read line; do array[$b_ip]="$line" b_ip=$(($b_ip+1)) echo -e ${NET}.${RED}${line}${NC} done < ${TMP1}

max_b=${#array[@]} for (( ip=${max_b}; ip<=253; ip++ )); do array[$ip]=0 done

b=0 for (( i=1; i<=254 ; i++ )); do if (( ${array[$b]} != ${i} ));then echo -e ${NET}.${BLUBG}${i}${NC} else b=$(($b+1)) fi done

echo -e "В подсети ${NET}.0/24 занято: ${RED} ${max_b} ${NC} адреса(ов)." echo -e "В подсети ${NET}.0/24 свободно: ${BLUBG} `expr 254 - ${max_b}` ${NC} адреса(ов)."

rm -f ${TMP1} rm -f ${TMP2}

exit 0

Можно и проще наверно все написать.

P.S.:
причем вот эту часть скрипта пришлось дописывать, так как вылазила ошибка из за того что индекс массива закончился

text

max_b=${#array[@]}
for (( ip=${max_b}; ip<=253; ip++ )); do
    array[$ip]=0
done
#372779

"prostornet" написал:
Вывод все равно не дает желаемого результата.
что вам не нравится-то?

PS: ЯННП в вашем скрипт. Может вы его перепишете по-человечески? Это нормально, все так делают.
#372782

Пардон, был не прав. Стоило сразу переписать...

text

#!/bin/bash

A=(2 10 11 54 69 101 155 156 199 202)

RED='\033[31m' BLUBG='\033[44m' NC='\033[0m'

MAX_INDEX_A=${#A[@]}

for (( INDEX_A=0; INDEX_A<=MAX_INDEX_A; INDEX_A++ )); do echo -e ${RED}${A[INDEX_A]}${NC} done

for (( INDEX_A=${MAX_INDEX_A}; INDEX_A<=253; INDEX_A++ )); do A[$INDEX_A]=0 done

# Вместо массива B, использовал перебор цифр (в данном примере от 1 до 254) INDEX_B=0 for (( i=1; i<=254 ; i++ )); do if (( ${A[$INDEX_B]} != ${i} ));then echo -e ${BLUBG}${i}${NC} else INDEX_B=$(($INDEX_B+1)) fi done

echo -e "Номеров в массиве А и В: ${RED} ${MAX_INDEX_A} ${NC}." echo -e "Номеров только в массиве В: ${BLUBG} `expr 254 - ${MAX_INDEX_A}` ${NC}."

exit 0

Войдите или зарегистрируйтесь, чтобы ответить.