Как мне сравнить буквенно-цифровые символы в непоследовательном порядке?

#awk

#awk

Вопрос:

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

В своем текущем состоянии, помимо простого сравнения чисел, он дополнительно выполняет две вещи :

  1. В настоящее время он учитывает нули перед числом или символом и сравнивает только абсолютные значения, игнорируя нули перед числом или символом

  2. В настоящее время, если одно и то же число или символ встречается несколько раз в обоих файлах, это выводит дополнительное событие

я просто хочу, чтобы скрипт хорошо работал с буквенно-цифровыми символами, так как в настоящее время он, похоже, хорошо работает только с простыми числами. Может кто-нибудь, пожалуйста, отредактировать скрипт, чтобы получить желаемый результат, также учитывая вышеуказанные 2 условия

Текущий скрипт

 awk '{k=$0 0} 
       NR==FNR {a[k]  ; next} 
       !(k in a amp;amp; a[k]-->0); 
       END {for(k in a) while(a[k]-->0) print k}' file1 file2
  

Пример ниже

файл cat1

 1
01
001
8
2B
12
13C
027B
0027B
  

cat file2

 1
2
08
12
13C
02B
9
27B
  

Ожидаемый результат

 1
1
2
9
27B
  

Объяснение ожидаемого результата

 In file1 : "1" , "01" , "001" evaluates to 1 * 3 times
In file 2 : "1" is present only once
Hence "1" is present twice in result ( 3-1 times )
  
 "2" and "9" are exclusively present in file2 , So obviously both simply form part of output 
  
 In file1 : '027B" , "0027B" evaluates to 27B * 2 times
In file 2 - "27B" is present only once
Hence '27B" is present once in result ( 2 -1 times )
  

Объяснение совпадающих элементов (которые не являются частью ожидаемого результата)

 "8" from file1 ( line 4 )is matched with "08" from file2 ( line 3)
"12" from file1 ( line 6) is matched with "12" from file2 ( line 4)
"13C" from file1 (line 7 ) is matched with "13C" from file2 ( line 5 )
"2B" from file1 ( line 5 ) is matched with "02B" from file2 ( line 6 )
  

Наконец, порядок элементов в ожидаемом выводе должен быть в порядке возрастания, как показано в моем примере выше, допустим, если в приведенном выше примере ожидаемый вывод имел 3, он должен читаться по вертикали как 1 1 2 3 9 27B

Комментарии:

1. Это непонятно, не могли бы вы, пожалуйста, пояснить, почему 8 и 13c не входит в ожидаемый результат вашего?

2. У File1 есть «8» в 4-й строке, а у file2 было «08» в 3-й строке, абсолютное значение совпадает. «13C» присутствует в file1 в 3-й последней строке и 5-й строке в file2, поэтому его совпадение, следовательно, оба не являются частью ожидаемого результата

3. В файле 1 — 1, 01,001 вычисляется 1 * 3 раза, 1 присутствует в file2 один раз, поэтому он является частью выходных данных дважды (3-1 раз). 2 и 9 присутствуют исключительно в file2 . 0027B, а 027B оценивается как 27B, присутствующий дважды в файле 1 и один раз в file2, поэтому образует часть выходных данных один раз (2-1 раз). Я также предоставил объяснение для других выходных элементов.

4. Не могли бы вы, пожалуйста, проверить один раз paste <(awk '{sub(/^0 /,"")} 1' file1) <(awk '{sub(/^0 /,"")} 1' file2) | awk '$1==$2' и сообщить мне, если это то, что вы ищете? Я все еще не понял ваш вопрос.

5. @RavinderSingh13 получил эту ошибку — zsh: ошибка синтаксического анализа рядом с `)’

Ответ №1:

Этого должно быть достаточно, чтобы удалить начальные нули при формировании ключа (с особым случаем для нулевых значений, таких как 0000 ):

 /^0 $/ { k = 0 }
/[^0]/ { k = $0; sub(/^0*/, "", k) }
NR==FNR {a[k]  ; next}
!(k in a amp;amp; a[k]-->0);
END {for(k in a) while(a[k]-->0) print k}

$ awk -f a.awk file1 file2 
2
9
27B
1
1
  

ОТРЕДАКТИРУЙТЕ

Если вы просто хотите, чтобы значения были отсортированы численно, перейдите в раздел сортировка:

 $ awk -f a.awk file1 file2 | sort -n
1
1
2
3
4
5
9
27B
  

Для вывода в порядке, указанном в file2, вы можете запомнить порядок в другом массиве, а затем выполнить всю печать в КОНЕЧНОМ блоке. Эта версия будет выводить значения в порядке file2, причем любые значения только в file1 будут напечатаны последними.

 /^0 $/ { k = 0 }
/[^0]/ { k = $0; sub(/^0*/, "", k) }
NR==FNR {a[k]  ; next}

{ b[FNR] = k }
!(k in a amp;amp; a[k]--) { a[k] = 1 }
END { 
  for (i=1; i<=FNR;   i) {
    k = b[i]
    while(a[k]-->0) print k
  }
  for (k in a) {
    while(a[k]-->0) print k
  }
}

$ awk -f a.awk file1 file2 
1
1
2
9
27B
3
4
5
  

Комментарии:

1. Похоже, что этот скрипт не работает, если перед буквенно-цифровым символом присутствует ноль.. Первый момент в моем вопросе — он должен сравнивать только абсолютное значение числа, и это должно быть сохранено. Я только что добавил 02B в рассматриваемый файл 2, и теперь он не функционирует должным образом, выводит как 2B, так и 02B. он должен рассматривать 02B как совпадающий с 2B, как будто он соответствует 02 с 2

2. Смотрите обновленную версию, которая работает для таких случаев, как 2B / 02B

3. спасибо, кажется, теперь это работает, наконец, возможно ли отсортировать результат в порядке возрастания, аналогичном ожидаемому результату моего вопроса

4. Обновите версией, которая выводится в соответствии с порядком в file2

5. Хорошо, надеюсь, на этот раз я все понял 🙂 Попробуйте «повторно отредактировать» и давайте посмотрим.