如何将目录中的所有变量保存在一个文件中

How to save all variables from directory, in one file

我想将目录中的所有变量保存在一个单独的文件中,删除重复项 首先,我将所有带有全局变量的行写在一个单独的文件中

grep -rI "$.*" folder/ >> output.txt

然后我尝试拉出这个文件的变量

cat output.txt | sed /$.*.[{A-Z}]/p

并且输出不是我预期的

那么当像这样在 grep 之后文件时,我如何获取所需的变量:

something.text_text.txt:    - export IMAGE_NAME=${MY_REGISTY}/$MY_PR/${MY_PRNNN} something.text_text.txt:
- docker build --network host -t ${IMAGE_NAME}:${VERSION} -f $DILE_PATH --build-arg setupfile=$SET_FIL> something.text_text.txt: 
- docker push ${IMAGE_NAME}:${VERSION} something.text_text.txt:    - docker tag ${IMAGE_NAME}:${VERSION} ${IMAGE_NAME}:${MY_BUILD_REF_NAME} something.text_text.txt:    - docker push ${IMAGE_NAME}:${MY_BUILD_REF_NAME} something.text.txt:  
- /^rel_.*$/ something.text.txt:    - eval $(ssh-agent -s) something.text.txt:    - chmod 400 $MY_SSH_KEY something.text.txt:  
- ssh-add $MY_KEY something.text.txt:    - git checkout ${MY_BUIL_NAME} something.text.txt:    - git reset --hard origin/${MY_F_NAME} something.text.txt:    - mvn -s MY_settings.xml ${MTS} license:add-third-party something.text.txt:    - cat ${LICENSE_LIST_FILE} something.text.txt:      POM_XML_COMMIT_HASH_LOCAL=$(git log --oneline --follow -- pom.xml | awk '{ print  }' | head -n 1) || true something.text.txt:      echo POMIT_HASH_LOCAL=${PCOMMIT_HASH_LOCAL} something.text.txt:      POM_XML_COMMIT_HASH_REMOTE=$(git log --oneline origin/${MY_BUILD_REF_NAME} --follow -- pom.xml | awk '{ print  }' | h> something.text.txt:      echo POM_XML_COMMIT_HASH_REMOTE=${POM_OMMIT_HASH_REMOTE} something.text.txt:      if [[ ${POM_XML_COMMIT_HASH_LOCAL} = ${POMMIT_HASH_REMOTE} ]]; then something.text.txt:        echo "File pom.xml is the same for local and origin ${MY_BUILD_REF_NAME} branch." something.text.txt:        echo "New commits are presented in origin/${MY_BUILD_REF} branch for pom.xml file. Skipping." something.text.txt:    - git add -f ${LICENSE_LIST_FILE} something.text.txt:    - export MY_PUSH_URL=`echo $MY_REPOSITORY_URL | perl -pe 's#.*@(.+?(\:\d+)?)/#git@:#'` something.text.txt:    - git remote set-url --push origin "${MY_PUSH_URL}" something.text.txt:    - git push -f -o ci.skip origin ${MY_BUILD_REF_NAME} something.text_tests.txt:    - docker login -u $MY_REGISTRY_USER -p $MY_REGISTRY_PASSWORD $MY_REGISTRY something.text_tests.txt:    - export CONFIG_FILE=${HOME}/.docker/config.json something.text_tests.txt:   
- export VERSION=$(cat current_version) something.text_tests.txt:    - export MY_PROJECT_NAME_UPPER_CASE=$(echo ${MY_PROJECT_NAME} | tr a-z A-Z) something.text_tests.txt:    - export ${MY_PROJECUPPER_CASE}_IMAGE=${MYISTRY}/${MY_PROJECT_PATH}/${MY_PROJECT_NAME}:${VERSION} something.text_tests.txt:    - docker pull ${MY_REG}/${MY_PR}/${MY_PROJEC}:${VERS}

尝试

grep -Po '$\.*.[{_A-Z}]+' output.txt
  • -P 使用 Perl 语法使 grep
  • -o只输出匹配的部分

现在,改进您的正则表达式。对于初学者,我已经向其中添加了 _,但它仍然会找到 ${X}{Y}(误报)或找不到 ${lowercase}(漏报)并且只是部分找到 ${DIR#/} (因为额外的语法)。

您可以使用 --only-matching 或简单的 -o 告诉 grep 只输出匹配的部分。 这里真正的问题是什么才是真正有效的变量标识符。这当然取决于 shell 编写的脚本以及脚本的原作者使用了多少种不同的风格。

让我们假设一些理智的东西,标识符以 [a-Z] 开头并且只能包含字母数字字符和下划线。您还可以使用 $MY_VARIABLE${MY_VARIABLE}.

引用相同的标识符

我会选择类似的东西:

grep -rhIo '$[a-zA-Z_\{\}]*' directory | sort --unique

但请注意,数组的语法和变量之上的操作会很快打破这一点。

要获得 ${adjacent}text 的正确结果,可以选择

grep -hrEo '$\{?[A-Za-z_0-9]+\}?' .

这对于

仍然无法正常工作
: <<\_
literal $text in a quoted here document
_
echo '$quoted literal text'
echo $escaped $dollar $signs
etc

但是对于快速而肮脏的尝试,也许只是忽略那些极端情况,或者添加某种后处理来删除它们。 正确解决这个问题需要你有一个 sh 解析器来确定引用了哪些美元符号等; eval 即使那样也不完整。

作为对此处其他答案的评论,grep -P 不可移植,需要 GNU grep。如果您没有那个,并且确实需要 Perl 正则表达式扩展,也许只需使用 Perl。

perl -lne 'print($&) while m/$\{?[A-Za-z_0-9]+\}?/go' **/*

**/* 递归通配符也不可移植;如果你需要一个 POSIX 兼容的脚本,也许求助于

find . -type f -exec \
    'print($&) while m/$\{?[A-Za-z_0-9]+\}?/go' {} +

当然 Perl 也不是 POSIX。