在bash脚本中从URL中提取文件名和路径

Are*_*rek 26 url bash parsing

在我的bash脚本中,我需要从给定的URL中提取路径.例如,从包含字符串的变量:

HTTP://登录:password@example.com/one/more/dir/file.exe一个=某物&B =某物

我想提取到其他变量只有:

/one/more/dir/file.exe

部分.当然登录,密码,文件名和参数是可选的.

由于我是sed和awk的新手,我请求你帮忙.拜托,建议我怎么做.谢谢!

JES*_*Sii 78

bash中有内置函数来处理这个问题,例如字符串模式匹配运算符:

  1. '#'删除最小匹配前缀
  2. '##'删除最大匹配前缀
  3. '%'删除最小匹配后缀
  4. '%%'删除最大匹配后缀

例如:

FILE=/home/user/src/prog.c
echo ${FILE#/*/}  # ==> user/src/prog.c
echo ${FILE##/*/} # ==> prog.c
echo ${FILE%/*}   # ==> /home/user/src
echo ${FILE%%/*}  # ==> nil
echo ${FILE%.c}   # ==> /home/user/src/prog
Run Code Online (Sandbox Code Playgroud)

所有这些都来自优秀的书:"Mark G. Sobell的Linux命令,编辑和Shell编程实用指南"(http://www.sobell.com/)

  • 以为我会告诉你这篇文章对我很有帮助.谢谢! (4认同)
  • 对于URL,我会使用 - "printf - "%s""$ {URL ##*/}"` - 这将删除导致最终"/"的任何内容,并且与方案无关. (2认同)
  • 请注意,如果您有查询字符串参数,则需要使用2个单独的参数替换行,或者您可以通过sed管道 - "printf - "%s""$ {url ##*/}"| sed's /?.*//'`取代了可选项?什么都没有. (2认同)

sae*_*gnu 30

在bash中:

URL='http://login:password@example.com/one/more/dir/file.exe?a=sth&b=sth'
URL_NOPRO=${URL:7}
URL_REL=${URL_NOPRO#*/}
echo "/${URL_REL%%\?*}"
Run Code Online (Sandbox Code Playgroud)

仅当URL以http://或具有相同长度的协议开始时才起作用否则,使用正则表达式可能更容易sed,grep或者cut......

  • 我永远不会理解为什么/当人们发布*辉煌的*例子,**没有**明显包含`示例输出`.例如,这里......一条简单的线,就是所有需要的......`↳/ one/more/dir/file.exe` (5认同)
  • 强迫懒惰的用户自己尝试一下?!:d (4认同)

Jim*_*Jim 7

这使用bashcut作为另一种方式.这很难看,但它有效(至少在这个例子中).有时候我喜欢用我称之为切割的筛子来减少我实际需要的信息.

注意:性能方面,这可能是一个问题.

鉴于这些警告:

首先让我们回应一下:

echo 'http://login:password@example.com/one/more/dir/file.exe?a=sth&b=sth'
Run Code Online (Sandbox Code Playgroud)

这给了我们:

HTTP://登录:password@example.com/one/more/dir/file.exe一个=某物&B =某物

然后让我们在@ 切割线作为一种方便的方法去掉http:// login:password:

echo 'http://login:password@example.com/one/more/dir/file.exe?a=sth&b=sth' | \
cut -d@ -f2
Run Code Online (Sandbox Code Playgroud)

这给了我们这个:

example.com/one/more/dir/file.exe?a=sth&b=sth

为了摆脱主机名,让我们做另一个剪切并使用/作为分隔符,同时要求剪切给我们第二个字段和之后的所有内容(基本上,到行的末尾).它看起来像这样:

echo 'http://login:password@example.com/one/more/dir/file.exe?a=sth&b=sth' | \
cut -d@ -f2 | \
cut -d/ -f2-
Run Code Online (Sandbox Code Playgroud)

反过来,这导致:

一个/多个/目录/的file.exe?A =某物&B =某物

最后,我们想从最后剥离所有参数.再次,我们将使用cut,这次是作为分隔符并告诉它只给我们第一个字段.这让我们走到了尽头,看起来像这样:

echo 'http://login:password@example.com/one/more/dir/file.exe?a=sth&b=sth' | \
cut -d@ -f2 | \
cut -d/ -f2- | \
cut -d? -f1
Run Code Online (Sandbox Code Playgroud)

输出是:

一个/多个/目录/的file.exe

只是另一种方法,这种方法是一种方法,以交互方式削减您不需要的数据,以提出您需要的东西.

如果我想把它填充到脚本中的变量中,我会做这样的事情:

#!/bin/bash

url="http://login:password@example.com/one/more/dir/file.exe?a=sth&b=sth"
file_path=$(echo ${url} | cut -d@ -f2 | cut -d/ -f2- | cut -d? -f1)
echo ${file_path}
Run Code Online (Sandbox Code Playgroud)

希望能帮助到你.


cal*_*fir 5

仅使用 bash 内置函数:

path="/${url#*://*/}" && [[ "/${url}" == "${path}" ]] && path="/"
Run Code Online (Sandbox Code Playgroud)

其作用是:

  1. 删除前缀*://*/(所以这将是您的协议和主机名+端口)
  2. 检查我们是否确实成功删除了任何内容 - 如果没有,则意味着没有第三个斜杠(假设这是一个格式良好的 URL)
  3. 如果没有第三个斜杠,那么路径就是/

注意:这里实际上不需要引号,但我发现使用它们更容易阅读


ken*_*orb 5

url="http://login:password@example.com/one/more/dir/file.exe?a=sth&b=sth"
Run Code Online (Sandbox Code Playgroud)

GNU grep

$ grep -Po '\w\K/\w+[^?]+' <<<$url
/one/more/dir/file.exe
Run Code Online (Sandbox Code Playgroud)

BSD grep

$ grep -o '\w/\w\+[^?]\+' <<<$url | tail -c+2
/one/more/dir/file.exe
Run Code Online (Sandbox Code Playgroud)

ripgrep

$ rg -o '\w(/\w+[^?]+)' -r '$1' <<<$url
/one/more/dir/file.exe
Run Code Online (Sandbox Code Playgroud)

要获取 URL 的其他部分,请检查:获取 URL 的部分(正则表达式)