使用 sed 在每一行的开头添加一个 URL

λ J*_*kas 6 bash sed wget

我有某个网页的 URL(见下文),其中列出了许多不同版本的软件包。

URL=http://ftp.gnu.org/gnu/wget/
Run Code Online (Sandbox Code Playgroud)

下面的一行代码从 HTML 中获取了最新版本的 tar ball 及其签名文件。

wget -qO- http://ftp.gnu.org/gnu/wget/ | grep tar | cut -d\" -f6 | tail -n4 | grep gz
Run Code Online (Sandbox Code Playgroud)

可能不是最短最有效的一个班轮,但是嘿,我正在学习,我愿意接受反馈。上面的结果是这样的:

wget-1.15.tar.gz
wget-1.15.tar.gz.sig
Run Code Online (Sandbox Code Playgroud)

现在,下一个逻辑步骤(至少对我),是管上方插入到输出 sed并追加$URL到每行的前面,使得输出看起来像:

http://ftp.gnu.org/gnu/wget/wget-1.15.tar.gz
http://ftp.gnu.org/gnu/wget/wget-1.15.tar.gz.sig
Run Code Online (Sandbox Code Playgroud)

然后我想通过管道将其重新导入wget以下载文件。

问题是:如何使用 将 bash 变量的值附加$URL到每行输出的前面sed?我尝试了以下方法:

sed "s/^/$URL/"
Run Code Online (Sandbox Code Playgroud)

但这只会给我错误:

sed: -e expression #1, char 11: unknown option to `s'
Run Code Online (Sandbox Code Playgroud)

我也知道基本概念是好的,因为当我使用以下时,我得到了很好的结果......

VAR="Gorauskas, "
echo "Jonas" | sed "s/^/$VAR/"
Run Code Online (Sandbox Code Playgroud)

所以,我的猜测是我需要以某种方式转义变量/中的所有字符 $URL......我在正确的轨道上吗?

dev*_*ull 11

使用不包含变量中任何字符的不同分隔符。

例如,

sed "s|^|$URL|"
Run Code Online (Sandbox Code Playgroud)

(如果您/用作分隔符并且模式或替换也包含/,那么您需要转义它们。)

  • 在 URL 中要注意的另一个字符(在一般情况下,不是这里)是 `&`,因为它是替换右侧的 `sed` 的特殊字符。 (6认同)

Hau*_*ing 8

到目前为止,您所做的一切都可以用一个awk电话代替:

wget ... | awk -F\" '$6 ~ "gz$" { lastline=thisline; thisline=$6;}; '\
  'END {print lastline; print thisline;}'
Run Code Online (Sandbox Code Playgroud)

当然,awk 也可以添加 URL:

awk -F\" -v baseurl="http://ftp.gnu.org/gnu/wget/" \
  '$6 ~ "gz" { lastline=thisline; thisline=$6;}; '\
  'END {print baseurl lastline; print baseurl thisline;}'
Run Code Online (Sandbox Code Playgroud)


Sté*_*las 8

您可以在此处使用wget's--base选项:

wget -qO- http://ftp.gnu.org/gnu/wget/ |
  cut -d\" -sf6 |
  grep '\.tar\.gz' |
  tail -n2 |
  wget -i - --base=http://ftp.gnu.org/gnu/wget/
Run Code Online (Sandbox Code Playgroud)


ter*_*don 5

你也可以像这样直接做整个事情:

wget -qO- http://ftp.gnu.org/gnu/wget/ | grep tar.gz | cut -d\" -f6 | 
 tail -n2 | xargs -I{} wget http://ftp.gnu.org/gnu/wget/{}
Run Code Online (Sandbox Code Playgroud)

此经过第一输出wgetxargs它取代了字符串{}与每个管道命令的结果的。

您可以使用一些技巧跳过一些解析步骤:

wget -qO- http://ftp.gnu.org/gnu/wget/ | tac | grep -Pom 2 'href="\K(.+?.tar.gz)' | 
xargs -I{} wget http://ftp.gnu.org/gnu/wget/{}
Run Code Online (Sandbox Code Playgroud)

在这里,我们使用PCREs ( -P)grep-o所以它只打印行的匹配部分,并且-m 2只打印前 2 个匹配项。该tac调用反转输入,以便前 2 个匹配项实际上是最后一个(tac反转其输入,将最后一行打印为第一行,倒数第二行作为第二行等)。

\K正则表达式告诉grep忽略任何之前来到\K,使用时不会打印等等-o


另一种更接近您的想法的方法是循环读取目标文件:

wget -qO- http://ftp.gnu.org/gnu/wget/ |tac | 
 grep -Pom 2 'href="\K(.+?.tar.gz)' | 
    while read target; do 
        wget http://ftp.gnu.org/gnu/wget/"$target"; 
    done 
Run Code Online (Sandbox Code Playgroud)