通过grep逐行迭代结果,不按空格分隔

Met*_*kin 2 bash grep

我正在使用bash脚本来识别某些内容的使用位置,然后找到相应的引用(名称).

该脚本是:

#!/bin/bash

echo "running, searching for instances of ${1:0:1}/$1"

for i in ls -d Module*; do
    if [ -d "$i" ]; then
        if [ -f $i/003.Design/003.Data.efx ]; then
            if grep -qe "Module-0000/003.Design/005.Types/${1:0:1}/$1" $i/003.Design/003.Data.efx; then
                echo $i $i/003.Design/003.Data.efx
                grep -B 4 "Module-0000/003.Design/005.Types/${1:0:1}/$1" $i/003.Design/003.Data.efx | grep "name"
            fi
        fi
    fi
done
Run Code Online (Sandbox Code Playgroud)

我正在尝试将其更改为:

#!/bin/bash

echo "running, searching for instances of ${1:0:1}/$1"
for i in ls -d Module*; do
    if [ -d "$i" ]; then
        if [ -f $i/003.Design/003.Data.efx ]; then
            if grep -qe "Module-0000/003.Design/005.Types/${1:0:1}/$1" $i/003.Design/003.Data.efx; then
                echo $i $i/003.Design/003.Data.efx
                for j in `grep -B 4 "Module-0000/003.Design/005.Types/${1:0:1}/$1" $i/003.Design/003.Data.efx | grep "name"` ; do
                    echo $j
                done
            fi
        fi
    fi
done
Run Code Online (Sandbox Code Playgroud)

当我进行上述更改以迭代结果时,结果全部搞砸了.我怀疑我的使用for是不正确的.

我应该注意到更改前的结果是:

$ ./findEllipseType.sh AveragePrice
running, searching for instances of A/AveragePrice
Module-3110 Module-3110/003.Design/003.Data.efx
      <ownedAttribute xmi:id="_P7sUcAg7EdysLcyAWbYneA" name="EstPrice">
Module-3140 Module-3140/003.Design/003.Data.efx
      <ownedAttribute xmi:id="_Z2v4IaW-EduyI4lEFgFo8g" name="StoresSalePrice">
      <ownedAttribute xmi:id="_bpCVJaW-EduyI4lEFgFo8g" name="StoresSalePrice">
      <ownedAttribute xmi:id="_j0crsMnVEeOm9cfLF6jryw" name="EstPrice">
Module-3210 Module-3210/003.Design/003.Data.efx
      <ownedAttribute xmi:id="_dYMlpaW-EduyI4lEFgFo8g" name="GrossPriceP">
      <ownedAttribute xmi:id="_duQVQqW-EduyI4lEFgFo8g" name="GrossPriceP">
      <ownedAttribute xmi:id="_dujQI6W-EduyI4lEFgFo8g" name="CurrNetPrP">
      <ownedAttribute xmi:id="_eNZISqW-EduyI4lEFgFo8g" name="GrossPriceP">
      <ownedAttribute xmi:id="_eNi5QKW-EduyI4lEFgFo8g" name="PrevGpP">
      <ownedAttribute xmi:id="_eNsqQqW-EduyI4lEFgFo8g" name="CurrNetPrP">
      <ownedAttribute xmi:id="_eNsqSqW-EduyI4lEFgFo8g" name="PrevNetPrP">
      <ownedAttribute xmi:id="_fRV4kqW-EduyI4lEFgFo8g" name="CurrNetPrP">
      <ownedAttribute xmi:id="_fRV4mqW-EduyI4lEFgFo8g" name="GrossPriceP">
      <ownedAttribute xmi:id="_fgsjMqW-EduyI4lEFgFo8g" name="EstPrice">
      <ownedAttribute xmi:id="_fg1tJaW-EduyI4lEFgFo8g" name="ActGrossPr">
Module-3560 Module-3560/003.Design/003.Data.efx
      <ownedAttribute xmi:id="_xM44IKW-EduyI4lEFgFo8g" name="UnitPrice">
      <ownedAttribute xmi:id="_xOYF8KW-EduyI4lEFgFo8g" name="UnitPrice">
      <ownedAttribute xmi:id="_xdbOkKW-EduyI4lEFgFo8g" name="AmendPrice">
Run Code Online (Sandbox Code Playgroud)

但是,当我进行更改时,它显示为(截断):

$ ./findEllipseType.sh AveragePrice
running, searching for instances of A/AveragePrice
Module-3110 Module-3110/003.Design/003.Data.efx
<ownedAttribute
xmi:id="_P7sUcAg7EdysLcyAWbYneA"
name="EstPrice">
Module-3140 Module-3140/003.Design/003.Data.efx
<ownedAttribute
xmi:id="_Z2v4IaW-EduyI4lEFgFo8g"
name="StoresSalePrice">
<ownedAttribute
xmi:id="_bpCVJaW-EduyI4lEFgFo8g"
name="StoresSalePrice">
<ownedAttribute
xmi:id="_j0crsMnVEeOm9cfLF6jryw"
name="EstPrice">
Module-3210 Module-3210/003.Design/003.Data.efx
<ownedAttribute
xmi:id="_dYMlpaW-EduyI4lEFgFo8g"
Run Code Online (Sandbox Code Playgroud)

查看结果,for in当我希望它使用行分隔符时,似乎使用了空格分隔符.我该如何更改?

mkl*_*nt0 7

tl;博士:

  • 更改for i in ls -d Module*; dofor i in Module*/;do
  • 更换
for j in `grep -B 4 "Module-0000/003.Design/005.Types/${1:0:1}/$1" $i/003.Design/003.Data.efx | grep "name"` ; do
  echo $j
done
Run Code Online (Sandbox Code Playgroud)

while IFS= read -r j; do 
  echo "$j"
done < <(grep -B 4 "Module-0000/003.Design/005.Types/${1:0:1}/$1" "$i/003.Design/003.Data.efx" | grep "name")
Run Code Online (Sandbox Code Playgroud)

请参阅下面的完整讨论.


for i in ls -d Module*; do将简单地枚举令牌ls,-d和(可能膨胀)Module*,而不是列举输出ls命令.

要纠正这个直接问题,你必须使用命令substitution(for i in $(ls -d Module*; do)),但这是不可取的,因为直接使用globbing(路径名扩展)是一个强大而合适的解决方案:for i in Module*/; do

类似地,不建议使用for循环逐行解析命令输出,因为输出受到单词拆分以及其他shell扩展的影响.
实际上,for循环枚举了以空格分隔的标记而不是整行.

使用while带有IFS= read -r通过进程替换提供的输入的循环是正确的方法 - 它确保未经修改地读取行.

此外,通常建议对引用变量引用进行双引号以避免不必要的shell扩展.

因此,修改后的代码形式为:

shopt -s nullglob  # ensure that a glob matching nothing expands to empty string
for i in Module*/; do 
  if [[ -f "$i/003.Design/003.Data.efx" ]]; then
    if grep -qe "Module-0000/003.Design/005.Types/${1:0:1}/$1" "$i/003.Design/003.Data.efx"; then
      echo "$i $i/003.Design/003.Data.efx"
      while IFS= read -r j; do 
        echo "$j"
      done < <(grep -B 4 "Module-0000/003.Design/005.Types/${1:0:1}/$1" "$i/003.Design/003.Data.efx" | grep "name")
    fi
  fi
done
Run Code Online (Sandbox Code Playgroud)