【问题标题】:Bash capturing in brace expansion大括号扩展中的 Bash 捕获
【发布时间】:2019-10-03 13:04:02
【问题描述】:

在正则表达式中使用捕获组之类的东西进行大括号扩展的最佳方法是什么。例如:

touch {1,2,3,4,5}myfile{1,2,3,4,5}.txt

产生数字和 25 个不同文件的所有排列。但如果我只想拥有像1myfile1.txt2myfile2.txt、...这样的文件,第一个和第二个数字相同,这显然是行不通的。因此,我想知道最好的方法是什么? 我正在考虑捕获第一个数字,然后再次使用它。理想情况下没有琐碎的循环。

谢谢!

【问题讨论】:

  • 请编辑您的 Q 以包括可测试的输入、所需的输出以及您解决问题的最佳尝试。我认为您将需要一个for 循环。祝你好运。
  • 当然,我知道循环,但是无法以某种方式捕获?
  • 你说的是匹配'/^[[:digit:]]+myfile[[:digit:]]+.txt/'(扩展正则表达式)之类的东西吗?或者,您可以将printf "%s\n" {1,2,3,4,5}myfile{1,2,3,4,5}.txt 写入临时文件并使用grep -f tmpfile ... 进行匹配。
  • bash 中有正则表达式捕获组,但没有大括号扩展。
  • 谢谢@chepner。这回答了我问题的核心。

标签: bash brace-expansion


【解决方案1】:

不使用正则表达式,而是使用 for loop 和序列 (seq),您会得到相同的结果:

for i in $(seq 1 5); do touch ${i}myfile${i}.txt; done

或者更整洁:

 for i in $(seq 1 5); 
 do 
   touch ${i}myfile${i}.txt; 
 done

例如,使用echo 代替touch

➜ for i in $(seq 1 5); do echo ${i}myfile${i}.txt; done
1myfile1.txt
2myfile2.txt
3myfile3.txt
4myfile4.txt
5myfile5.txt

【讨论】:

  • 不要使用seq。如果您使用bash,只需使用C 风格的for 循环:for ((i=1;i<=5;i++)); do。如果您想符合 POSIX,那么 seq 也不是 POSIX 的一部分,您可以使用 while 循环:i=1; while [ "$i" -le 5 ]; do ...; i=$((i+1); done
【解决方案2】:

MTwarog 的答案变体,少了一个管道/子流程:

$ echo {1..5} | tr ' ' '\n' | xargs -I '{}' touch {}myfile{}.txt
$ ls -1 *myfile*
1myfile1.txt
2myfile2.txt
3myfile3.txt
4myfile4.txt
5myfile5.txt

【讨论】:

    【解决方案3】:

    您可以使用 AWK 来做到这一点:

    echo {1..5} | tr ' ' '\n' | awk '{print $1"filename"$1".txt"}' | xargs touch
    

    解释:

    echo {1..5} - 打印数字范围
    tr ' ' '\n' - 将数字拆分为单独的行
    awk '{print $1"filename"$1}' - 使您能够使用以前打印的数字格式化输出
    xargs touch - 将文件名传递给 touch 命令(创建文件)

    【讨论】:

    • 或者你可以在awk中使用for循环。
    • printf '%d\n' {1..5} | xargs -I{} touch {}filename{}.txt
    • 您可以使用 awk 的 system("touch " $1"filename"$1".txt")(带括号)代替 printf 在 awk 中执行它。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-01-10
    • 2012-02-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多