Как я могу использовать sed для отображения строк между первой пустой строкой и последней строкой?

Попробуйте:

$ 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
1
21.08.2020, 23:21
2 ответа

Проблема в том, что в выходных данных 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 ).

2
18.03.2021, 23:10

В соответствии с 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"
    }
}
1
18.03.2021, 23:10

Теги

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