Совместите два шаблона в одной строке и напечатайте их в два столбца - PullRequest
0 голосов
/ 14 декабря 2018

У меня около нескольких сотен CSV-файлов.Эти CSV-файлы имеют разные определения, и я не хочу вручную объединять все CSV-файлы в один формат.

Я хочу получить две разные вещи из файлов - A и B, и я могу сопоставить обаих с регулярным выражением.Я хочу сопоставить их обоих одновременно - поэтому будут напечатаны только строки с обоими вещами.Я знаю, как это сделать, и я видел много сообщений SO, отвечающих, как это сделать.

Но я не знаю, как напечатать просто A B без остатка строки.Я не знаю, в каком порядке или в каких столбцах будут эти две вещи, поэтому я не знаю, как (или даже могу ли я) использовать awk.

Пример:

(соответствует A [0-9], B [0-9])

A0 B0 C0
B1 C1 D1
E2 C2 A2
C3 F3 F3
B4 F4 A4

Результат:

A0 B0
A4 B4

Ответы [ 2 ]

0 голосов
/ 14 декабря 2018

Но я не знаю, как печатать только AB без остатка строки.

Ну, вам нужно удалить все, кроме A и B, из совпадающих строк и заставить awkпересчитать поля ($1=$1 делает это).

awk '/A[0-9]/ && /B[0-9]/ { gsub(/[^AB][0-9]/,""); $1=$1; print }' file
0 голосов
/ 14 декабря 2018

1-е решение: с использованием match функции awk.Он будет выводить в порядке от буквы A к B в соответствии с показанными примерами OP.

awk '
match($0,/A[0-9]+/){
  val=substr($0,RSTART,RLENGTH)
  if(val && match($0,/B[0-9]+/)){
     print val,substr($0,RSTART,RLENGTH)
  }
}'  Input_file


2-е решение: Это решение будетне заботятся о буквах A и B, поэтому в том порядке, в котором они располагаются, они будут отображаться в том же порядке.

awk '
{
  for(i=1;i<=NF;i++){
    if($i ~ /A[0-9]+/ || $i ~ /B[0-9]+/){
       val=val?val OFS $i:$i
    }
  }
  if(val ~ /A[0-9]+/ && val ~ /B[0-9]+/){
    print val
  }
  val=""
}
END{
  if(val ~ /A[0-9]+/ && val ~ /B[0-9]+/){
    print val
  }
}'   Input_file


3-е решение: , учитывая, что они нужны в порядке от A до B на выходе, тогда может помочь следующее:

awk '
{
  for(i=1;i<=NF;i++){
     line=$i
     sub(/[0-9]+/,"",line)
     if($i ~ /A[0-9]+/ || $i ~ /B[0-9]+/){
       array[tolower(line)]=$i
     }
  }
  if(array["a"] ~ /A[0-9]+/ && array["b"] ~ /B[0-9]+/){
     print array["a"],array["b"]
  }
  delete array
}
END{
  if(array["a"] ~ /A[0-9]+/ && array["b"] ~ /B[0-9]+/){
     print array["a"],array["b"]
  }
}'   Input_file

ПРИМЕЧАНИЕ: Добавление информации из man awk документация по используемым функциям, например -> match, tolower, RSTART и RLENGTH

match (s, r [, a]) Возвращает позицию в s, гдевстречается регулярное выражение r или 0, если r отсутствует, и задает значения RSTART и RLENGTH.Обратите внимание, что порядок аргументов такой же, как и для оператора ~: str ~ re.Если указан массив a, a очищается, а затем элементы с 1 по n заполняются частями s, которые соответствуют соответствующему заключенному в скобки подвыражению в r.0-й элемент a содержит часть s, совпадающую со всем регулярным выражением r.Подскрипты a [n, "start"] и a [n, "length"] предоставляют начальный индекс в строке и длине соответственно каждой соответствующей подстроки.

RSTART Индекс первого символасоответствует match ();0 если нет совпадений.(Это означает, что индексы символов начинаются с единицы.)

RLENGTH Длина строки, совпадающей с match ();-1, если совпадения нет.

tolower (str) Возвращает копию строки str, в которой все символы в верхнем регистре в str транслируются в соответствующие им символы нижнего регистра.Неалфавитные символы остаются без изменений.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...