Modify the content of variable using sed (or something similar)

∥☆過路亽.° 提交于 2020-12-05 05:07:09

问题


I wrote a BASH file that features multiple embedded loops of the form

for P in {'0.10','0.20', [...] '0.90','1.00'}; do 
   for Q in {'0.10','0.20', [...] ,'0.90','1.00'}; do
    [...] 

I use these variables both as parameters for a command line application, and to create file names directly in BASH. I would like to create duplicates, say $P_REP=0_10 that replaces the dot by an underscore without writting a explicit switch statement for every case, or some hardcoded equivalent. The (non-elegant way) I found to go about it is to

  1. dump the content of P,Q to a temporary file.
  2. replace the dot by an underscore using sed 's/./_/ -i.
  3. read the file again and load its content to the new variable.

Hence, I was wondering if it is possible to run a sed like command directly on the content of a variable?


回答1:


You can do pattern substitution directly in bash:

P_REP=${P/./_}
Q_REP=${Q/./_}

From the bash(1) man page:

Paramter Expansion

${parameter/pattern/string}

Pattern substitution. The pattern is expanded to produce a pattern just as in pathname expansion. Parameter is expanded and the longest match of pattern against its value is replaced with string. If pattern begins with /, all matches of pattern are replaced with string. Normally only the first match is replaced. If pattern begins with #, it must match at the beginning of the expanded value of parameter. If pattern begins with %, it must match at the end of the expanded value of parameter. If string is null, matches of pattern are deleted and the / following pattern may be omitted. If parameter is @ or *, the substitution operation is applied to each positional parameter in turn, and the expansion is the resultant list. If parameter is an array variable subscripted with @ or *, the substitution operation is applied to each member of the array in turn, and the expansion is the resultant list.




回答2:


John Kugelman's answer is fine for your example, but if you need to process the content of a variable with the actual sed program (or some other arbitrary command), you can do it like this:

P_REP=$(sed 's/\./_/' <<< "$P")



回答3:


For loops you could use:

#!/bin/bash
P_REP=$(for P in '0.10' '0.20' '0.90' '1.00'; do echo ${P/./_} ; done)
Q_REP=$(for Q in '0.10' '0.20' '0.90' '1.00'; do echo ${Q/./_} ; done)

echo ${P_REP[@]}
echo ${Q_REP[@]}



回答4:


For the exact problem you are mentionning, use John's proposition above.

I would however mention, in case you ever have to do something similar that can't be solved with bash's pattern substitution syntax, that you don't need to actually create temporary files to transform content with sed or similar commands. First, you can pipe a variable directly to a program as STDIN. Second, you may get the output of a command (oeither it's STDOUT, STDERR, or both) directly into a shell variable.

So in your example, you would have had:

for P in 0.10 0.20 [...] 0.90 1.00 ; do 
   for Q in 0.10 0.20 [...] 0.90 1.00 ; do
        P_REP=$( sed 's/\./_/g' <<< "$P" )
        Q_REP=$( sed 's/\./_/g' <<< "$Q" )
   done
done

Note also that the array syntax (that is { '0.10', '0.20', ...}) is mostly specific to Bash and a very few Bash-followers. When it is easy to do so, you might prefer the more classical approach to for loops in shell, as I domonstrated above. Then your code will safetly execute in all posix-compliant shells.




回答5:


Why so complicated there is simple solution You are changing ALL substrings ALL files in Folder / Catalog

ORG="orignal_string"
DES="destination_string"
find . -type f -exec sed -i 's/'"${ORG}"'/'"${DES}"'/g' {} +


来源:https://stackoverflow.com/questions/19551613/modify-the-content-of-variable-using-sed-or-something-similar

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!