首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在bash shell中使用for循环和sed拆分字符串

在bash shell中使用for循环和sed拆分字符串
EN

Stack Overflow用户
提问于 2019-12-09 14:31:45
回答 2查看 301关注 0票数 0

变量中有以下字符串:

-rw-r--r-- 0 1068 1001 4870 Dec 6 11:58 1.zip -rw-r--r-- 0 1068 1001 20246 Dec 6 11:59 10.zip

我试图用for循环循环这个字符串,并得到以下结果:

代码语言:javascript
运行
复制
Dec 6 11:58 1.zip
Dec 6 11:59 10.zip

有人有正确的sed命令来做这件事吗?

所以让我把我的问题说得更清楚一点。我使用sftp文件执行-b命令,在其中执行ls -l *.zip命令。结果会进入一个文件中。首先,我使用一个sed命令来清除前2行,因为对我来说这些都是无关的信息。我现在只有ls结果,但它们在一行上。在我的例子中,只有2个zip文件,但是可以有更多。

代码语言:javascript
运行
复制
 ListOfFiles=$(sed '1,2d' $LstFile) #delete first 2 lines
    for line in $ListOfFiles
    do
        $line=$(echo "${line}" | sed (here i want the command to ony print zip file and date)
    done
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-12-09 15:44:07

关于订正设想方案的说明

这个问题已被修改为包括一个shell片段:

ListOfFiles=$(sed '1,2d‘$LstFile) #删除$ListOfFiles do $line=$中行的前2行

将结果保存到变量中,就像在第一行中一样,这是处理它的错误方法。您可以使用我原来答案中的代码的简单调整(下面)来简单地实现您的需求--非常简单地使用awk,但是如果您挂在使用sed上,就可以使用sed对原始代码进行简单的调整。

awk 变体

代码语言:javascript
运行
复制
awk 'NR <= 2 { next } { print $6, $7, $8, $9 }' $LstFile

NR <= 2 { next }部分跳过前两行;其余行不变,只是数据源是您下载的列表文件。

sed 变体

代码语言:javascript
运行
复制
sed -nE -e '1,2d' -e 's/^([^ ]+[ ]+){5}([^ ]+([ ]+[^ ]+){3})$/\2/p' $LstFile

实际上,1,2d命令不太可能是必要的,但使用它更安全,以防前两行中的一行有9个字段。(是的,我可以避免两次使用-e选项-不,我更喜欢在单独的选项中使用单独的命令;这样可以更容易地阅读IMO。)

原来问题的答案

如果将此视为字符串操作中的练习(不考虑尝试parse the output from ls reliably的正当警告),则不需要sed。事实上,sed几乎肯定是该工作的错误工具-- awk将是一个更好的选择--但是可以单独使用shell。例如,假设数据位于字符串$variable中,可以使用:

代码语言:javascript
运行
复制
set -- $variable
echo  $6  $7  $8  $9
echo $15 $16 $17 $18

这给了你18个位置参数,并打印了你感兴趣的8个。使用awk,您可以使用:

代码语言:javascript
运行
复制
echo $variable | awk '{ print $6, $7, $8, $9; print $15, $16, $17, $18 }'

这两种方法都会在空格处自动拆分字符串,并允许您引用带有数字的拆分元素。使用sed,您不会得到自动拆分,这使得工作非常麻烦。

假设变量实际上包含两行,因此:

代码语言:javascript
运行
复制
echo "$variable"

报告:

代码语言:javascript
运行
复制
-rw-r--r-- 0 1068 1001  4870 Dec 6 11:58 1.zip
-rw-r--r-- 0 1068 1001 20246 Dec 6 11:59 10.zip

上面的代码假定$variable的内容是一行(尽管如果变量包含两行,它将保持不变),但是下面的代码假设它包含两行。实际上,如果$variable包含许多行,下面的代码就可以工作,而setawk版本则绑定到“输入中的18个字段”。

假设-E选项到sed启用了扩展正则表达式,那么您可以使用:

代码语言:javascript
运行
复制
variable="-rw-r--r-- 0 1068 1001  4870 Dec 6 11:58 1.zip
-rw-r--r-- 0 1068 1001 20246 Dec 6 11:59 10.zip"
echo "$variable" |
sed -nE 's/^([^[:space:]]+[[:space:]]+){5}([^[:space:]]+([[:space:]]+[^[:space:]]+){3})$/\2/p'

它查找一系列非空白字符,然后是一个空白字符序列,重复5次,然后是一个非空白字符序列,以及3组空白序列,然后是一个非空白序列。分组括号--从而将字段1-5选择为\1 (忽略字段),将字段6-9选择为\2 (保留字段),然后打印结果。如果您决定不使用选项卡等,则可以将sed命令简化为:

代码语言:javascript
运行
复制
echo "$variable" | sed -nE 's/^([^ ]+[ ]+){5}([^ ]+([ ]+[^ ]+){3})$/\2/p'

这两种产品的产出如下:

代码语言:javascript
运行
复制
Dec 6 11:58 1.zip
Dec 6 11:59 10.zip

处理输入的单行变体是非常痛苦的

注意,使用$variable中的两行值,awk版本可能变成:

代码语言:javascript
运行
复制
echo "$variable" | awk '{ print $6, $7, $8, $9 }'

这也将处理任意数量的行。

注意理解echo $variableecho "$variable"之间的区别是多么重要。第一种方法将所有空白序列视为等效于单个空白,而另一种则保留内部间隔。以及捕获输出,例如:

代码语言:javascript
运行
复制
variable=$(ls -l 1*.zip)

保留赋值中的间距(特别是换行符)(请参见Capturing multiple line output into a Bash variable)。因此,sed显示的应用于您的可能性不大,但这并不确定,因为在发布此答案之前,您没有回答所要求的澄清。

票数 1
EN

Stack Overflow用户

发布于 2019-12-09 15:47:35

正如其他人说的那样,您不应该真的解析ls输出。否则,一种使用awk打印您感兴趣的列的虚拟方法:

代码语言:javascript
运行
复制
awk '{print $6, $7, $8, $9 "\n" $15, $16, $17, $18}' <<< $your_variable
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59251015

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档