如果我有一些包含HTTP标题和正文的文本,例如:
HTTP/1.1 200 OK
Cache-Control: public, max-age=38
Content-Type: text/html; charset=utf-8
Expires: Fri, 22 Nov 2013 06:15:01 GMT
Last-Modified: Fri, 22 Nov 2013 06:14:01 GMT
Vary: *
X-Frame-Options: SAMEORIGIN
Date: Fri, 22 Nov 2013 06:14:22 GMT
<!DOCTYPE html>
<html>
<head>
<title>My website</title>
</head>
<body>
Hello world!
</body>
</html>
这个文本是从一个命令输入的,如何删除标题只留下身体?
(在标题中,\r\n
用作换行符。\r\n\r\n
标记标题的结尾和正文的开头。)
以下是我尝试的内容(...
表示任何命令,例如cat
或curl
,它会将一些HTTP标头和正文输出到标准输出):
我的第一个想法是使用sed
进行替换,以便在第一次出现\r\n\r\n
之前删除所有内容:
... | sed 's|^.*?\r\n\r\n||'
但这不起作用,主要是因为sed
仅对各行进行操作,因此无法在\r
或\n
上运行。 (此外,它不支持?
非贪婪的运算符。)
我还考虑过将grep
与\r\n\r\n
一起使用... | grep -oP '(?<=\r\n\r\n).*'
:
grep
但这也不起作用(主要是因为pcregrep
仅对各行进行操作)。
-M
有一个多线模式(pcregrep
),但perl
通常不可用(默认情况下不会在Ubuntu 12.04,Mac OS X 10.7等中安装),而我我想要一个不需要任何非标准工具的解决方案。
然后我考虑使用/s
代替.
,以便... | perl -pe 's/^.*?\r\n\r\n//s'
匹配换行符:
$/
我认为这更接近于一个有效的解决方案。但是,我认为Perl的输入记录分隔符(\n
)默认为\r\n
,需要更改为.
,以便\r\n
可以匹配-0
。 $/
选项可用于将... | perl -pe '$/ = "\r\n"; s/^.*?\r\n\r\n//s'
设置为单个字符,但不能设置为多个字符。我试过这个,但我不认为这是正确的:
^
另外,我认为\r\n\r\n
匹配“行首”,但需要匹配“文件开头”。
我想知道BodyOffset=$(expr index "$MyHttpText" "\r\n\r\n")
的偏移使用:
HttpBody=${MyHttpText:BodyOffset}
然后使用:
将主体提取为子串expr
不幸的是,index
的Mac OS X版本不支持#
。另外,如果可能的话,我想要一个不需要创建变量的解决方案。
我的另一个想法是使用参数替换,其中$MyHttpText
表示“从*\r\n\r\n
中移除与$MyHttpText
的前端匹配的HttpBody=${MyHttpText#*\r\n\r\n}
的最短部分” :
{{1}}
但是我不知道如何在一个管道序列的命令中使用它,而且我更喜欢一个不需要变量的解决方案。
答案 0 :(得分:8)
sed可以做到这一点:
sed '1,/^$/d' data.txt
此命令删除从第1行开始的所有内容,并在第一次出现空行(^$
)时结束。如果您将\n
作为换行符,则此方法有效。如果您有\r\n
作为换行符,则可以使用dos2unix
和unix2dos
来回转换它们,也可以将\r
字符添加到sed } regex:
sed '1,/^\r$/d' data.txt
但是,最后一行仅在\r\n
作为换行符时才有效,为了使其适用于两种类型的换行符,您可以使用:
sed '1,/^\r\{0,1\}$/d' data.txt
这里我们正在寻找一个带有0或1个\r
字符的空行。
答案 1 :(得分:2)
你的Perl单行命令没有(不能)删除标题,因为它当时只读取一行输入。您需要取消设置输入记录分隔符以将整个输入读取为一行。
perl -0777 ...
答案 2 :(得分:1)
在bash中也很有趣(仅限内部命令):
#!/bin/bash
while read LINE #<-- while you can read line from input
do #<-- do the following actions
if [ $FLAG ] #<-- if: this flag is set
then echo "$LINE" #<-- echo the input to output
elif [ ${LINE:0:1} = $'\r' ] #<-- else: if line starts with \r
then FLAG=true #<-- then raise the flag
fi
done
答案 3 :(得分:0)
... | perl -ne 'print if $after_header; $after_header = 1 if /^\r$/'
答案 4 :(得分:0)
curl默认不会从bash返回标题。因此,在你的卷发电话中没有指定治疗方法!