bash 如何在bash中替换字符串中的空格和斜杠?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/22107691/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to replace spaces and slash in string in bash?
提问by harrison4
Giving the string:
给出字符串:
foo='Hello \
World! \
x
we are friends
here we are'
Supose there are also tab charactersmixed with spaces after or before the \
character.
I want to replace the spaces, tabs and the slash by only a space. I tried with:
假设还有制表符在\
字符前后混合有空格。我只想用一个空格替换空格、制表符和斜杠。我试过:
echo "$foo" | tr "[\s\t]\\[\s\t]\n\[\s\t]" " " | tr -s " "
Returns:
返回:
Hello World! x we are friend here we are
And the result I need is:
我需要的结果是:
Hello World! x
we are friends
here we are
Some idea, tip or trick to do it? Could I get the result I want in only a command?
一些想法,提示或技巧来做到这一点?我可以只用一个命令就得到我想要的结果吗?
采纳答案by Gerrit Brouwer
The following one-liner gives the desired result:
以下单行给出了所需的结果:
echo "$foo" | tr '\n' '\r' | sed 's,\s*\\s*, ,g' | tr '\r' '\n'
Hello World!
we are friends
here we are
Explanation:
解释:
tr '\n' '\r'
removes newlines from the input to avoid special sed behavior for newlines.
tr '\n' '\r'
从输入中删除换行符以避免换行符的特殊 sed 行为。
sed 's,\s*\\\s*, ,g'
converts whitespaces with an embedded \ into one space.
sed 's,\s*\\\s*, ,g'
将带有嵌入 \ 的空格转换为一个空格。
tr '\r' '\n'
puts back the unchanged newlines.
tr '\r' '\n'
放回未更改的换行符。
回答by John B
You could use a read
loop to get the desired output.
您可以使用read
循环来获得所需的输出。
arr=()
i=0
while read line; do
((i++))
[ $i -le 3 ] && arr+=($line)
if [ $i -eq 3 ]; then
echo ${arr[@]}
elif [ $i -gt 3 ]; then
echo $line
fi
done <<< "$foo"
回答by jaypal singh
With awk
:
与awk
:
$ echo "$foo"
Hello \
World! \
x
we are friends
here we are
With trailing newline:
带有尾随换行符:
$ echo "$foo" | awk '{gsub(/[[:space:]]*\[[:space:]]*/," ",$ echo "$foo" |
awk '{
gsub(/[[:space:]]*\[[:space:]]*/," ",$ echo "$foo" | awk -v RS='^$' -v ORS= '{gsub(/\s+\\s+/," ")}1'
Hello World! x
we are friends
here we are
)
a[++i] = #!/bin/bash
foo="Hello \
World!"
echo $foo | sed 's/[\s*,\]//g'
}
END {
for(;j<i;) printf "%s%s", a[++j], (ORS = (j < NR) ? "\n\n" : "\n")
}' RS= FS='\n'
Hello World! x
we are friends
here we are
)}1' RS= FS='\n' ORS='\n\n'
Hello World! x
we are friends
here we are
.
Without trailing newline:
没有尾随换行符:
foo='Hello \
World!'
bar=$(tr -d '\' <<<"$foo")
echo $bar # unquoted!
回答by Ed Morton
sed is an excellent tool for simple subsitutions on a single line but for anything else just use awk. This uses GNU awk for multi-char RS (with other awks RS='\0'
would work for text files that don't contain NUL chars):
sed 是一个很好的工具,用于在一行上进行简单的替换,但对于其他任何事情,只需使用 awk。这将 GNU awk 用于多字符 RS(其他 awkRS='\0'
可用于不包含 NUL 字符的文本文件):
Hello World!
回答by Alex
Try as below:
尝试如下:
bar=$(tr -d '\' <<<"$foo" | tr -s '[:space:]' " ")
bar=$(perl -0777 -pe 's/\$//mg; s/\s+/ /g' <<<"$foo")
回答by glenn Hymanman
If you just want to print the output as given, you just need to:
如果您只想打印给定的输出,您只需要:
$ foo="Hello \
World"
$ echo "$foo"
Hello World
$ foo='Hello \
World!
here we are'
$ echo "$foo"
Hello \
World!
here we are
$ echo "$foo" | perl -0777 -pe 's/(\s*\\s*\n\s*)/ /sg'
Hello World!
here we are
If you want to squeeze the whitespace as it's being stored in the variable, then one of:
如果您想压缩存储在变量中的空格,则可以使用以下方法之一:
foo='Hello \
World! \
x
we are friends
here we are'
The advantage of the perl version is that it only removes line continuation backslashes (at the end of the line).
perl 版本的优点是它只删除行连续反斜杠(在行尾)。
Note that when you use double quotes, the shell takes care of line continuations (proper ones with no whitespace after the slash:
请注意,当您使用双引号时,shell 会处理行的延续(斜杠后没有空格的正确行:
sed -r ':s; s/( )? *\ *$//; Te; N; bs; :e; s/\n *//g' <<< "$foo"
So at this point, it's too late.
所以在这一点上,为时已晚。
If you use single quotes, the shell won't interpret line continuations, and
如果您使用单引号,shell 将不会解释换行符,并且
Hello World! x
we are friends
here we are
回答by John Kugelman
while (s/( )? *\ *$//) { # While there's a backslash to remove, remove it...
N # ...and concatenate the next line.
}
s/\n *//g # Remove all the newlines.
If you use double quotes then the shell will interpret the \
as a line continuation character. Switching to single quotes preserves the literal backslash.
如果您使用双引号,则 shell 会将其解释\
为行继续符。切换到单引号会保留文字反斜杠。
I've added an backslash after World!
to test multiple backslash lines in a row.
World!
在连续测试多个反斜杠行之后,我添加了一个反斜杠。
foo='Hello \
World!'
shopt -s extglob
echo "${foo/+( )\*( )$'\n'/ }"
Hello World!
Output:
输出:
##代码##What's this doing? In pseudo-code you might read this as:
这是在做什么?在伪代码中,您可以将其读为:
##代码##In detail, here's what it does:
详细来说,这是它的作用:
:s
is a branch labeleds
for "start".s/( )? *\\ *$/\1/
replaces a backslash and its surrounding whitespace. It leaves one space if there was one by capturing( )?
.- If the previous substitution failed,
Te
jumps to labele
. N
concatenates the following line, including the newline\n
.bs
jumps back to the start. This is so we can handle multiple consecutive lines with backslashes.:e
is a branch labelede
for "end".s/\n *//g
removes all the extra newlines from step #4. It also removes leading spaces from following line.
:s
是一个标记s
为“开始”的分支。s/( )? *\\ *$/\1/
替换反斜杠及其周围的空格。如果通过捕获有一个空间,它会留下一个空间( )?
。- 如果之前的替换失败,则
Te
跳转到 labele
。 N
连接以下行,包括换行符\n
。bs
跳回起点。这样我们就可以用反斜杠处理多个连续的行。:e
是一个标记e
为“结束”的分支。s/\n *//g
从步骤#4 中删除所有额外的换行符。它还从下一行中删除前导空格。
Note that T
is a GNU extension. If you need this to work in another version of sed, you'll need to use t
instead. That'll probably take an extra b
label or two.
请注意,这T
是一个 GNU 扩展。如果您需要它在另一个版本的 sed 中工作,则需要t
改用它。这可能需要额外的一b
两个标签。
回答by carlpett
As I understand, you want to just remove trailing spaces followed by an backslash-escaped newline?
据我了解,您只想删除尾随空格,后跟反斜杠转义的换行符?
In that case, search with the regex ( ) *\\\n
and replace with \1
在这种情况下,使用正则表达式搜索( ) *\\\n
并替换为\1
回答by iruvar
With bashisms such as extended globbing, parameter expansionetc...but it's probably just as ugly
使用扩展 globbing、参数扩展等bashisms ......但它可能同样丑陋
##代码##