欢迎各位兄弟 发布技术文章
这里的技术是共享的
如果不使用
你不能。为什么必须使用
?
您是否爱上
命令:)?为什么没有其他Linux命令?
如果没有
或
:
。
@jaynesh如zfus正确猜中,是的,这是家庭作业,我们不能使用sed或awk。如果我有几行简单的文本,其中每一行都是一个网址,则有一个定界符。我需要从那些网址中提取最后一个字段,即com,net,nz。但是数量。 (定界符)始终随每个地址而变化,但始终是最后一个字段。我认为削减是显而易见的选择:
如果将问题仅限于期望的答案(在本例中为
),则您将无法学习任何新知识。
如何在shell中拆分字符串并获取最后一个字段的可能重复项
这也很愚蠢:仅
不能执行此任务。您需要其他工具。因此,您不能使用
或
,但是可以使用
和
?调用内联
或
脚本怎么办?完全不使用
怎么办?
@MestreLion很多时候,人们阅读问题以找到解决问题的方法。这从错误的前提开始,即
支持它不支持的功能。但是我认为它很有用,因为它迫使读者考虑更易于遵循的代码。我想要一种快速,简单的使用
的方法,而无需对
,
,
等使用多种语法。非常优雅,而且我从未考虑过(即使在其他情况下笨拙)。我也喜欢从其他答案中阅读其他方法。
@EliranMalka谢谢。感谢您的反馈。我在尝试。
这是一个现实生活中的问题:我想在源代码树中找到所有不同的文件扩展名,以更新.gitattributes文件。所以
是自然倾向
顺便说一句,@ studog,如果在GNU平台上,
将仅自行发出文件名。
您可以尝试这样的事情:
1 | echo 'maps.google.com' | rev | cut -d'.' -f 1 | rev |
说明
maps.google.com的反向为
使用点作为定界符并选择第一个字段,即
最后,我们再次将其反转(感谢提醒@tom)以获得
这个"仅
"如何?
它不仅使用
,而且不使用
或
。
在过去的几个小时中,@ tom OP不仅问了更多问题。根据与OP的交互,我们知道awk / sed / etc。不允许在他的家庭作业中使用,但尚未提及rev。所以值得一试
@zfus我明白了。之后可能要粘贴另一个
。
@zfus我认为您还需要另一个
,因为在类似
的情况下。
双
非常理想!
很棒,简单,完美,也感谢您的解释-没有足够的人来解释管道命令的长链中的每个步骤
如果您没有
,请尝试
使用参数扩展。这比包括
1 2 | data=foo,bar,baz,qux last=${data##*,} |
有关bash中本机字符串操作的介绍,请参见 BashFAQ#100 。
@ErwinWessels:因为bash真的很慢。使用bash运行管道,而不是批量处理数据。我的意思是,如果您在shell变量中已经有一行文本,或者您想执行
处理几行文本,那么这很好。但是对于大文件,rev | cut | rev可能更快! (当然awk会比那快。)
@PeterCordes,对于大文件来说,awk肯定会更快,但是要克服恒定因素的启动成本,awk会花费很多。 (还存在一些shell,例如ksh93,其性能接近awk,在此答案中给出的语法仍然有效; bash异常缓慢,但它甚至无法接近唯一可用的选项)。
谢谢@PeterCordes;像往常一样,我猜每个工具都有其用例。
到目前为止,这是在
脚本中精简单个变量的最快,最简洁的方法(假设您已经在使用
脚本)。无需调用任何外部。
虽然这看起来确实很整洁,但我还是更喜欢double rev,它不是bash特有的。它学到了我一个新工具!请注意,我一直使用bash,但永远不会提醒那些古怪而野蛮的语法。
@Balmipour,...,但是
特定于您使用的提供此功能的任何操作系统-尚未在所有UNIX系统上标准化。有关命令和实用程序的POSIX部分,请参见列出的章节-此处不存在。而且
实际上不是bash特定的;它在POSIX sh标准中,请参阅第2.6.2节(链接)的结尾,因此与
不同,它始终可在任何兼容的shell上使用。
@Balmipour,...如果您从事学习新工具的业务,则可以考虑学习具有良好运行时性能特征的工具的好处。 shell之所以以速度慢而闻名,其原因的一半是因为许多人习惯于编写效率低下的脚本,并在内部脚本会用时使用外部命令。 (另一半是我和Peter先前讨论的问题-解释器的性能-但是如果您在紧密的循环中扩展外部工具,那么比较起来,解释器的性能就不那么明显了)。
@Charles Duffy感谢您的精确度。我从不需要外壳脚本中的性能,但是就这一点以及它的POSIX标准(我不知道)的事实而言,您显然是正确的。猜猜选择在很大程度上取决于需求,但是我很乐意对此有所了解:)
要求切|转速快一点是完全没有根据的。与字符串扩展相比,它非常慢。在我的系统上,字符串扩展的10000次重复花费0.398秒。 rev | cut | rev耗时1分钟6秒
@ Bruno9779,因此,它取决于实现细节。如果您为要反转的每个字符串增加一个新的管道,那将非常慢-正如您所注意到的。如果您通过发送10,000个字符串来重用单个管道,则它会比同等的本机bash更快-这大概就是PeterCordes所说的。就是说,单管道重用实际上很少是实际可行的,因此我同意您的观点,通常来说,参数扩展是正确的选择。
@ Bruno9779,...提供了一个仅使用一个管道即可非常快速地处理大量行的具体示例:在
中,
覆盖的部分在我的本地系统上花费了0m0.026s挂钟时间。
您可以概括一下以得出最后一个领域的结论吗?
答案很容易适应以获取任何字段...
@GiacomoAlzetta,
-在ideone.com/gMUu1x上查看它的运行情况
仅使用
1 | grep -o '[^,]*$' |
用逗号分隔其他定界符。
若要执行相反的操作,并找到除最后一个字段以外的所有内容,请执行以下操作:
这特别有用,因为在我的情况下
添加了问题多字节unicode字符。
我试图在MinGW上执行此操作,但是我的grep版本不支持-o,所以我使用了
,该字符用空字符串替换直到最后一个逗号(包括最后一个逗号)的所有字符。
没有awk吗?
但是使用awk是如此简单:
1 | echo 'maps.google.com' | awk -F. '{print $NF}' |
AWK是一种功能更强大的工具,可以放在口袋里。
-F如果用于字段分隔符
NF是字段数(也代表最后一个的索引)
这是通用的,并且每次都完全按预期运行。在这种情况下,使用
实现OP的最终输出就像使用勺子"切"牛排(双关语:))。
是牛排刀。
避免不必要地使用
,这可能会降低使用
的长文件的脚本速度。
有多种方法。您也可以使用它。
1 2 3 | echo"Your string here"| tr ' ' ' ' | tail -n1 > here |
显然,tr命令的空格输入应替换为所需的定界符。
谢谢!在busybox sh 1.0.0中起作用的东西:)
这感觉像是对我来说最简单的答案,更少的管道和更清晰的含义
这不适用于整个文件,这可能是OP的意思。
这是仅使用cut的唯一可能解决方案:
echo"s.t.r.i.n.g." | cut -d'.' -f2-
[repeat_following_part_forever_or_until_out_of_memory:] | cut -d'.' -f2-
使用此解决方案,字段的数量确实可以是未知的,并且会不时变化。但是,由于行长不得超过LINE_MAX个字符或字段(包括换行符),因此,绝对不能将任意数量的字段作为此解决方案的实际条件。
是的,这是一个非常愚蠢的解决方案,但是唯一符合我认为标准的解决方案。
真好就拿最后一个。脱离" s.t.r.i.n.g."这可行。
当每个人都说某事是不可能的,然后有人听到一个可行的答案时,我会喜欢。即使确实很傻。
可以循环循环
,直到输出不再更改为止。
如果您的输入字符串不包含正斜杠,则可以使用
1 | $ basename"$(echo 'maps.google.com' | tr '.' '/')" |
这不使用
如果处理可能包含正斜杠的输入字符串,这将无法正常工作。解决该问题的方法是将正斜杠替换为您知道不是有效输入字符串的一部分的其他字符。例如,文件名中也不允许使用竖线(
1 | $ basename"$(echo 'maps.google.com/some/url/things' | tr '/' '|' | tr '.' '/')" | tr '|' '/' |
以下实现朋友的建议
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | #!/bin/bash rcut(){ nu="$( echo $1 | cut -d"$DELIM" -f 2- )" if ["$nu" !="$1" ] then rcut"$nu" else echo"$nu" fi } $ export DELIM=. $ rcut a.b.c.d d |
您需要在
的参数两边加上双引号,以使其可靠且可靠地工作。见stackoverflow.com/questions/10067266/
为这个老问题添加一个方法只是为了好玩:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | $ cat input.file # file containing input that needs to be processed a;b;c;d;e 1;2;3;4;5 no delimiter here 124;adsf;15454 foo;bar;is;null;info $ cat tmp.sh # showing off the script to do the job #!/bin/bash delim=';' while read -r line; do while [["$line" =~"$delim" ]]; do line=$(cut -d"$delim" -f 2- <<<"$line") done echo"$line" done < input.file $ ./tmp.sh # output of above script/processed input file e 5 no delimiter here 15454 info |
除了bash,仅使用cut。
好吧,我想是回声。
嗯,为什么不完全删除剪切并仅使用bash ... x]
如果您有一个名为filelist.txt的文件,该文件是诸如以下内容的列表路径:
c:/dir1/dir2/file1.h
c:/dir1/dir2/dir3/file2.h
那么您可以执行以下操作:
rev filelist.txt |切-d" /" -f1 |转速
我意识到,只要确保存在尾随定界符,它就会起作用。因此,在我的情况下,我有逗号和空格分隔符。我在最后添加一个空格;
1 2 3 | $ ans="a, b" $ ans+=""; echo ${ans} | tr ',' ' ' | tr -s ' ' | cut -d' ' -f2 b |
并且
产生
,它不满足"字段数未知或每行更改"的要求。
来自 https://www.codenong.com/22727107/