我有一个脚本,它添加了一个字符串C++源文件:
for f in $(find . -name '*.h' -or -name '*.cpp');
do sed -i '1s/^/<added text> /' $f;
done;
如何添加多行变量值?
尝试过,但没有成功:
h=$'//Copyright 2021 My Corporationn//Authors: me and othersn'
变量CCD_ 1变为单行。
使用ed
而不是sed
来编辑文件。
如果使用bash
:,也不需要使用find
来定位文件
#!/usr/bin/env bash
h=$'//Copyright 2021 My Corporationn//Authors: me and othersn'
# Turn on recursive globbing and extended globbing and have patterns that
# fail to match expand to an empty string
shopt -s globstar extglob nullglob
for f in **/*.@(h|cpp); do
# Add the contents of the variable h at the beginning of the file
# Note: no lines in $h should be just a period as that signals end of
# text input mode.
ed -s "$f" <<EOF
1i
$h
.
w
EOF
done
如果由于某种原因必须使用sed
,您还希望使用其i
命令,而不是s
(人们往往会忘记sed
甚至还有其他命令),它会插入以下文本行,直到末尾没有反斜杠的文本行标记最后一行输入。当然,需要一些h
0参数扩展来将变量转换为适当的形式:
#!/usr/bin/env bash
h=$'//Copyright 2021 My Corporationn//Authors: me and othersn'
# Add a newline at the very beginning, and a backlash at the end
# of each line
h=$'n'"${h//$'n'/$'\n'}"
# Or just format the original string appropriately at the start
# h=$'n//Copyright 2021 My Corporation\n//Authors: me and others\n'
shopt -s globstar extglob nullglob
for f in **/*.@(h|cpp); do
sed -i -e "1i\$h" "$f"
done
# If using GNU sed, you can avoid the loop:
# sed -si -e "1i\$h" **/*.@(h|cpp)
sed
在处理嵌入式(单字符)n
时可能有点不稳定;我们可以通过几种方式来解决这个问题。。。
样本输入文件:
$ cat xx
1
2
3
根据${h}
变量的定义,有几个sed
的想法:
1)用文字/单字符n
:定义的${h}
$ h=$'//Copyright 2021 My Corporationn//Authors: me and othersn'
$ sed "1 s|^|${h//$'n'/\n}|" xx
其中:
1 s|^|
-第1行,将行的开头替换为${h//$'n'/\n}
-将所有单字符n
更改为3字符\n
(转义的+
n
)- 注意:因为
/
字符显示在数据中,所以sed
命令需要不同的分隔符,因此|
2)${h}
定义为2个字符的+
n
:
$ h='//Copyright 2021 My Corporationn//Authors: me and othersn'
$ sed "1 s|^|${h///\}|" xx*
其中:
1 s|^|
-第1行,将行的开头替换为${h///\}
-转义所有(注意:这可能会导致
出现无法解释为控制字符的问题)
- 注意:因为
/
字符显示在数据中,所以sed
命令需要不同的分隔符,因此|
这两者都会生成:
//Copyright 2021 My Corporation
//Authors: me and others
1
2
3
一旦OP对结果满意,就可以添加-i
标志来执行就地更新。
使用sed是过度使用sed语法的限制。
改为使用cat
:
#!/usr/bin/env bash
# Some helpful settings to avoid editing the core code
corporation='Example INC'
authors=(
'me'
'someone'
'someone-else'
)
# Capture the year (require bash 4.2+)
# If older bash, use year="$(date '+%Y')"
printf -v year '%(%Y)T'
# Be sure tmp_file variable does not exist (may have been exported)
unset tmp_file
# Prepare EXIT trap to clean-up temporary file
trap 'rm -f -- "$tmp_file"' EXIT
# Safely create a temporary file to hold changes
tmp_file="$(mktemp)"
# Find .h or .cpp files and make it a null delimited records stream
find . ( -name '*.h' -or -name '*.cpp' ) -print0 |
# Iterate the null delimited file names
while read -r -d '' cpp_file; do
# Skip files already containing the copyright header
tail -n2 "$cpp_file" | grep -qF ' * Copyright' && continue
# If successfully merging here-document header with file
# into the temporary file
if cat - "$cpp_file" >"$tmp_file" <<EOF
/*
* Copyright ${year} ${corporation}
* Authors: ${authors[*]}
*
*/
EOF
# then copy the temporary file over
then cp "$tmp_file" "$cpp_file"
fi
done