如何将目录中的所有变量保存在一个文件中
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。
我想将目录中的所有变量保存在一个单独的文件中,删除重复项 首先,我将所有带有全局变量的行写在一个单独的文件中
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。