Как я могу отобразить первые пять строк, которые отличаются между двумя файлами, в сценарии оболочки? - PullRequest
0 голосов
/ 16 марта 2020

Я пытался использовать 2 массива для сравнения 2 файлов, но ima rook ie, и я не знаю, как это сделать:

vec_fis_1=`cat fisier.txt`
vec_fis_2=`cat fisier1.txt`
echo $vec_fis_2
echo $vec_fis_1
for i in ${vec_fis_1[@]}
do
        for j in ${vec_fis_2[@]}
        do
                if ( "$i" == "$j" )
                then
                        echo $i
                        echo $j
                fi
        done
done

Ответы [ 2 ]

0 голосов
/ 16 марта 2020

Не используйте backticks`. Вместо этого используйте $(..).

Поэтому вместо if ( "$i" == "$j" ) do if [ "$i" != "$j" ].

vec_fis_1 и vec_fis_2 не являются массивами - ${vec_fis_1[@]} - это то же самое, что $vec_fis_1 .

Чтобы прочитать файл в массив, используйте readarray.

Чтобы перебрать строки в файле, используйте while read loop, см. bashfaq, как прочитать строку файла с помощью line .

while IFS= read -r l1; do
     while IFS= read -r l2; do
         if [ "$l1" != "$l2" ]; then
            printf "%s\n" "$l1"
            printf "%s\n" "$l2"
         fi
     done < fisier1.txt
done < fisier.txt

Мне нужны только различия между строками с одинаковым "индексом строки"

Так что считывайте из обоих файлов одновременно.

while IFS= read -r -u3 l1 && 
         IFS= read -r -u4 l2; do
    if [ "$l1" != "$l2" ]; then
        printf "%s\n" "$l1"
        printf "%s\n" "$l2"
     fi
done 3< fisier.txt 4< fisier1.txt

Вы также можете обрабатывать различное количество строк. У меня есть эта (довольно многословная) идея:

while true; do

    IFS= read -r -u3 l1
    l1valid=$?
    IFS= read -r -u4 l2
    l2valid=$?
    if ((l1valid != 0 || l2valid != 0)); then
        if ((l1valid != 0 && l2valid == 0)); then
           echo "file1 is longer then file2"
        elif ((l1valid == 0 && l2valid != 0)); then
           echo "file1 is shorter then file2"
        fi # l1valid != 0 && l2valid != 0 - all fine
        break;
    fi

    if [ "$l1" != "$l2" ]; then
        printf "%s\n" "$l1"
        printf "%s\n" "$l2"
     fi

done 3< fisier.txt 4< fisier1.txt

или как:

while
    IFS= read -r -u3 l1
    l1valid=$?
    IFS= read -r -u4 l2
    l2valid=$?
    if ((l1valid != 0 && l2valid == 0)); then
       echo "file1 is longer then file2"
    elif ((l1valid == 0 && l2valid != 0)); then
       echo "file1 is shorter then file2"
    fi
    (( l1valid == 0 && l2valid == 0 ))
do
    if [ "$l1" != "$l2" ]; then
        printf "%s\n" "$l1"
        printf "%s\n" "$l2"
     fi
done 3< fisier.txt 4< fisier1.txt

Обратите внимание, что bash петли очень медленные, с awk они будут на несколько быстрее:

awk -vother="fisier1.txt" '{ t=$0; getline < (other); if (t != $0) print $0 RS t }' fisier.txt
0 голосов
/ 16 марта 2020

Из вашего вопроса не ясно, что именно вы хотите:

  1. вам нужно 5 разных строк из обоих файлов
  2. вам нужно 5 разных строк из каждого файла

Следующие примеры - не последние решения, а пища для дальнейших размышлений

Решение для первого случая - возьмите только различия и напечатайте первые 5 строк:

comm -3 FILE1 FILE2 | head -n5

Решение для второго случая - взять только различия и вывести 5 разных строк из каждого файла (всего 10 строк):

comm -3 FILE1 FILE2 | head -n10

Обновлено:

Примеры выше были предложены в предположении, что и FILE1 и FILE2 отсортированы. Если они не отсортированы, вам необходимо улучшить оба примера следующим образом:

comm -3 <( sort FILE1 ) <( sort FILE2 ) | ...

Примечания:

  1. Остальные команды (многоточие после канала) одинаковы.
  2. Это BASH способ
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...