AWK: как извлечь шаблон между двумя пользовательскими разделителями полей независимо от положения шаблона в строке?

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

The shell treats each character of IFS as a delimiter, and splits the results of the other expansions into words on these characters. If IFS is unset, or its value is exactly, the default, then sequences of,, and at the beginning and end of the results of the previous expansions are ignored, and any sequence of IFS characters not at the beginning or end serves to delimit words. If IFS has a value other than the default, then sequences of the whitespace characters space and tab are ignored at the beginning and end of the word, as long as the whitespace character is in the value of IFS (an IFS whitespace character). Any character in IFS that is not IFS whitespace, along with any adjacent IFS whitespace characters, delimits a field. A sequence of IFS whitespace characters is also treated as a delimiter. If the value of IFS is null, no word splitting occurs.
-bash(1)

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

  1. "сп"
  2. "~/some/dir/{мой -файл -в -переименовать.bin,"
  3. "новое -имя -файла -file.bin}"

Если бы у вас были кавычки или escape-последовательность "\", вы бы:

  1. "сп"
  2. "~/some/dir/{мой -файл -в -переименовать.bin,\ новое -имя -из -file.bin}"

Что также не будет тем, что вы хотели, если только «новое -имя -из -file.bin» не является новым именем файла, которое вы хотели. Пространство включено. Поскольку сначала происходит расширение скобок, а затем расширение тильды, bash будет выполняться:

  1. "сп"
  2. "/path/to/home/some/dir/my -file -to -rename.bin"
  3. "/path/to/home/some/dir/\ new -name -of -file.bin"

Простое удаление пробела исправило бы все это.

0
11.06.2020, 17:16
3 ответа

С помощью grepи cut. Используйте grep -o, чтобы взять oтолько совпадающие данные, найдите запрошенное поле и значение. Передайте это в cut, используя =в качестве разделителя полей, и возьмите второе поле:

$ grep -o 'MIC=[^,]*' input | cut -d= -f2
XAIM

С sed. Найдите запрошенную пару поле/значение, используйте ()и \1, чтобы извлечь соответствующий подшаблон:

$ sed -nE 's/^.*MIC=([^,]+).*$/\1/;p' input
XAIM
# or, alternatively,
$ sed -n 's/^.*MIC=\([^,]*\).*$/\1/;p' input
XAIM

С awk. Установите разделитель полей и разделитель записей на =и ,соответственно. Для записи с совпадающим шаблоном выведите второе поле (i. е. значение):

$ awk 'BEGIN { FS="="; RS=","; } $1 ~ /MIC/ { print $2 }' input
XAIM
0
28.04.2021, 23:18
$ sed -n 's/.* MIC=\([^,}]*\).*/\1/p' file
XAIM

При этом используется sedдля сопоставления строки  MIC=SOMETHING,или MIC=SOMETHING}и заменяется вся строка строкой SOMETHING. Все остальные данные отбрасываются.


$ tr ',' '\n' <file | awk -F '=' '$1 == " MIC" { print $2 }'
XAIM

Это сначала заменяет все запятые символами новой строки, а затем запускает awkс символом =в качестве разделителя полей. Когда первое поле равно  MIC, печатается второе поле.


$ awk -F ',' '{ for (i = 1; i <= NF; ++i) if (sub(" MIC=","",$i)) print $i }' file
XAIM

Это использует только awkи обрабатывает ввод как поля, разделенные запятыми. Он выполняет итерацию по всем полям, и когда поле начинается со строки  MIC=, эта строка удаляется из поля, а остаток печатается.


Если бы файл был в формате JSON (, я думаю, что вы, возможно, преобразовали данные из JSON в какой-то момент, так как большинство REST API возвращают ДАННЫЕ в формате JSON, и эти данные, похоже, связанные с финансовыми фондовыми рынками):

{
  "CU": "EUR",
  "GTPID": 144115188076657540,
  "II": "IT0005215329",
  "IS": 18814564,
  "LN": "FINE FOODS & PHARMACEUTICALS NTM",
  "MIC": "XAIM",
  "RIC": "FF.MI",
  "SG": "MA1",
  "SN": 801670,
  "STY": "ORDINARY",
  "TK": "0.0002 to 0.1,0.0005 to 0.2,0.001 to 0.5,0.002 to 1,0.005 to 2,0.01 to 5,0.02 to 10,0.05 to 20,0.1 to 50,0.2 to 100,0.5 to 200,1 to 500,2 to 1000,5 to 2000,10 to 5000,20 to 10000,50 to 20000,100 to 50000,200",
  "TS": "FF",
  "TY": "S",
  "UQ": 1
}

тогда jqбыло бы проще:

$ jq -r '.MIC' file1
XAIM
1
28.04.2021, 23:18

команда

 awk -F "," '{for(i=1;i<=NF;i++){if($i ~ /MIC/){gsub(/.*=/,"",$i);print $i}}}' 

имя файла

выход

XAIM
1
28.04.2021, 23:18

Теги

Похожие вопросы