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



我想保存所有的变量在一个单独的文件中,删除重复的目录首先,我在一个单独的文件

中编写了所有带有全局变量的行。
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 $1 }' | 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 $1 }' | 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@1:#'` 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}

Try

grep -Po '$.*.[{_A-Z}]+' output.txt
  • -P使grep使用Perl语法
  • -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是不可移植的,并且需要GNUgrep。如果您没有这些,并且确实需要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。