【问题标题】:bash substitution after glob not working?glob不起作用后的bash替换?
【发布时间】:2020-08-10 17:39:04
【问题描述】:

我在使用 bash 字符串替换时遇到了一个奇怪的行为。

我希望对 $r1 和 $var 进行相同的替换会产生完全相同的结果。 两个字符串似乎具有相同的值。

但事实并非如此,我无法理解我错过了什么......

也许是因为地球?我只是不知道...我不是纯粹的 IT 人员,也许这对你来说是显而易见的。

(Repl.it 链接底部)

mkdir -p T21805
touch T21805/T21805_SI-GA-D8-BH25N7DSXY_S1_L001_R1_001.fastq.gz

r1=T21805/*R1*
echo $r1;
echo ${r1%%_S1*z}
var=T21805/T21805_SI-GA-D8-BH25N7DSXY_S1_L001_R1_001.fastq.gz
echo ${var%%_S1*z}

echo $r1| hexdump -C
echo $var | hexdump -C

输出:

回声 $r1

T21805/T21805_SI-GA-D8-BH25N7DSXY_S1_L001_R1_001.fastq.gz

回声 ${r1%%_S1*z}

T21805/T21805_SI-GA-D8-BH25N7DSXY_S1_L001_R1_001.fastq.gz

回显 ${var%%_S1*z}

T21805/T21805_SI-GA-D8-BH25N7DSXY

回声 $r1| hexdump -C

00000000 54 32 31 38 30 35 2f 54 32 31 38 30 35 5f 53 49 |T21805/T21805_SI|

00000010 2d 47 41 2d 44 38 2d 42 48 32 35 4e 37 44 53 58 |-GA-D8-BH25N7DSX|

00000020 59 5f 53 31 5f 4c 30 30 31 5f 52 31 5f 30 30 31 |Y_S1_L001_R1_001|

00000030 2e 66 61 73 74 71 2e 67 7a 0a
|.fastq.gz.| 0000003a

回显 $var | hexdump -C

00000000 54 32 31 38 30 35 2f 54 32 31 38 30 35 5f 53 49 |T21805/T21805_SI|

00000010 2d 47 41 2d 44 38 2d 42 48 32 35 4e 37 44 53 58 |-GA-D8-BH25N7DSX|

00000020 59 5f 53 31 5f 4c 30 30 31 5f 52 31 5f 30 30 31 |Y_S1_L001_R1_001|

00000030 2e 66 61 73 74 71 2e 67 7a 0a
|.fastq.gz.| 0000003a

Repl.it

我有兴趣了解为什么这不起作用,例如,我可以使用 sed 实现我想要的输出。

【问题讨论】:

  • glob * 扩展为它在当前目录中匹配的文件。
  • 设置为第 7 行。我是通过复制/粘贴路径字符串来实现的。
  • @Jetchisel true 但它只是目录中的一个文件,并且通过 echo $r1 我检查了该值。
  • 因为您没有引用变量,这就是为什么当 glob 扩展时它与目录中的文件匹配。
  • r1=T21805/*R1* 当您执行 echo $r 时未引用 *R1* 展开并且它匹配目录中的文件 T218505,这只是一个 failure 引用问题。

标签: bash substring substitution


【解决方案1】:

分配时不会发生全局扩展。

$ mkdir -p T21805
$ touch T21805/T21805_SI-GA-D8-BH25N7DSXY_S1_L001_R1_001.fastq.gz
$ touch T21805/T21805_SI-GA-D8-BH25N7DSXY_S1_L001_R1_002.fastq.gz
$ r1=T21805/*R1*
$ printf '%s\n' "$r1"
T21805/*R1*
$ printf '%s\n' $r1
T21805/T21805_SI-GA-D8-BH25N7DSXY_S1_L001_R1_001.fastq.gz
T21805/T21805_SI-GA-D8-BH25N7DSXY_S1_L001_R1_002.fastq.gz

它发生在 未引用 r1 扩展之后。写${r1%%_S1*z}时,r1的值不包含字符串S1;只有 ${r1} 扩展之后才有S1 可以匹配。

如果设置数组,则赋值规则不同。 glob 会在赋值之前展开 ,因此您可以对数组的每个 元素 进行过滤。

$ r1=( T21805/*R1* )
$ printf '%2\n' "${r1[@]}"
T21805/T21805_SI-GA-D8-BH25N7DSXY_S1_L001_R1_001.fastq.gz
T21805/T21805_SI-GA-D8-BH25N7DSXY_S1_L001_R1_002.fastq.gz
$ printf '%s\n' "${r1[@]%%_S1*z}"
T21805/T21805_SI-GA-D8-BH25N7DSXY
T21805/T21805_SI-GA-D8-BH25N7DSXY

【讨论】:

    【解决方案2】:

    我在set -xv 之后运行它以查看 r1 的内容。

    $ r1=T21805/*R1*
    + r1='T21805/*R1*'
    
    $ var=T21805/T21805_SI-GA-D8-BH25N7DSXY_S1_L001_R1_001.fastq.gz
    + var=T21805/T21805_SI-GA-D8-BH25N7DSXY_S1_L001_R1_001.fastq.gz
    

    r1$ {r1 %% _ S1 * z}isT21805 / * R1 *

    r1 不包括_S1 * z

    【讨论】:

    • 设置什么 -xv ?
    • 我相信您可以查看我制作的 repl.it 链接,其中显示了此 MRE 的输出。 r1 的值和输出与你的明显不同。
    • 感谢您的评论。对不起,我英语不好,我会粘贴谷歌翻译结果。我现在修好了。
    • @RomainL.我检查了您创建的 repl.it 链接。
    • @RomainL.我运行了你的 main.sh (bash -xv main.sh)。结果还是一样,+ r1 = 'T21805 / * R1 *'。执行echo时,r1'T21805 / * R1 *'的内容会被展开。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-26
    相关资源
    最近更新 更多