Попробуйте:
$ cat infile
63 41,3,11,12
1 31,60,72,96
7 41,3,31,14,15,68,59,60
7 60,72,96
7 60
1 41,3,31,31,14,15,68,59,60
60 41,3,115,12,13,66,96
1 41,3,11,12,13,66,96 7 60,72,96
7 60
3 601
2 60,72,962
5 60,3
43 60
3 52360
$ grep -oP '^\s*[0-9]+(?= 60\s*$)' infile
7
7
43
Описание:
grep -P '^ # grep from start of line
\s* # followed by optional spaces
[0-9]+ # followed by some decimal digits
(?= 60\s*$) # That have a <space>60<space(s)><end of line>
# but do not capture the 60.
' infile
Проблема в том, что в выходных данных curl есть возврат каретки (CR ), поэтому шаблоны, подобные /^$/
, никогда не совпадают, поскольку каждая строка имеет CR и поэтому не пуста.
Есть несколько вещей, которые можно сделать: либо удалить CR, либо учесть их.
foo="$(curl -i http://127.0.0.1/404 | tr -d '\r')"
удалит их, а затем
printf '%s\n' "$foo" | sed '1,/^$/d'
будет работать или использовать, если я не удалил CR с помощьюtr
printf '%s\n' "$foo" | sed $'1,/^\r$/d'
Поскольку zsh может выполнять подстановку строк, я бы предпочел использовать
printf '%s\n' "${foo#*$'\r\n\r\n'}"
или
printf '%s\n' "${foo#*$'\n\n'}"
в зависимости от того, использовал ли я tr
для удаления CR,чтобы сохранить процесс sed.
Существует предостережение, однако :подстановка команд удаляет все конечные символы новой строки (кроме символов возврата каретки ). Ответ HTTP — <header1>CRLF...<headern>CRLFCRLF<body>
. Если <body>
пусто, $foo
будет содержать только <header1>CRLF...<headern>CRLFCR
или <header1>CRLF...<headern>
, если мы удалили CR. В этих случаях *$'\r\n\r\n'
или *$'\n\n'
не будут совпадать, и заголовки не будут удалены.
В любом случае, для печати произвольной строки, за которой следует символ новой строки, используется следующий синтаксис:
printf '%s\n' "$foo" # POSIX
print -r - "$foo" # ksh/zsh
echo -E - "$foo" # zsh
Не , который не работает должным образом, если echo "$foo"
$foo
содержит обратную косую черту (, распространенную в json ), или некоторые значения, начинающиеся с -
(, не должны иметь место для json ).
В соответствии с RFC7230 заголовки должны быть разделены парами CR -LF, затем парой CRLF (CRLF -CRLF)(в общих чертах :пустой строкой ), затем HTTP-ответ "тело". Таким образом, обычный http/1.1 будет содержать некоторые возврат каретки .
Не существует «пустой строки», как ее описывает Unix, т. е.никакая пара \n\n
не завершает заголовки. Это также означает, что для sed ^$
не будет соответствовать пустой строке (DOS )в конце заголовков, так как эта строка содержит\r
(Carriage Return ). В (GNU )sed альтернативой для обнаружения этой (почти )пустой строки может быть^\r$
:
$ printf '%s\n' "$foo" | sed '1,/^\r$/ d'
Если можно удалить символы возврата каретки, ответ http (все сообщение http/1.1, которое будет отправлено сервером ), будет содержать пустые строки в виде двух последовательных новых строк(\n\n
)для отделения заголовков от тела.
Если да, то специальное значение нулевогоRS
(режима абзаца в awk )может работать с этими заголовками:
$ echo "$foo" | tr -d '\r' | awk -v RS="" 'NR>1'
Или, чтобы обеспечить сохранение пустых строк в теле письма:
$ echo "$foo" | tr -d '\r' | awk 'BEGIN{ORS=RS="\n\n"}NR>1'
Тем не менее, почта (, как в RFC5322 ), и ответы http (, все сообщение http/1.1, как в RFC7230 ), должны использовать CR NL
в качестве маркера конца строки для заголовки . RS, который может содержать необязательный возврат каретки , требует регулярного выражения и использования терминатора записи RT (), поскольку он не является постоянным. Это означает, что следует использовать GNU awk.
$ echo "foo" | awk 'BEGIN{RS="(\r?\n){2}"}NR>1{printf "%s%s",$0,RT}'
{
"message": {
"status": "404",
"message": "Not Found"
}
}