我有一个文本文件,它有一个特定的行,比如
sometext sometext sometext TEXT_TO_BE_REPLACED sometext sometext sometext
我需要用上面的整行替换
This line is removed by the admin.
搜索关键字是TEXT_TO_BE_REPLACED
我需要为此编写一个 shell 脚本。我怎样才能做到这一点sed
?
您可以使用change命令替换整行,并使用-i
flag 就地进行更改。例如,使用 GNU sed:
sed -i '/TEXT_TO_BE_REPLACED/c\This line is removed by the admin.' /tmp/foo
您需要.*
在替换整行之前和之后使用通配符 ( ):
sed 's/.*TEXT_TO_BE_REPLACED.*/This line is removed by the admin./'
上面的答案:
sed -i '/TEXT_TO_BE_REPLACED/c\This line is removed by the admin.' /tmp/foo
如果替换字符串/行不是变量,则可以正常工作。
问题是在 Redhat 5 上转义\
后的. 双重也不起作用(至少在 Redhat 5 上)。c
$
\\
通过命中和试验,我发现如果您的替换字符串/行只有一行,那么\
后面是多余的。c
所以我没有\
在 之后使用c
,使用一个变量作为单个替换行,这很高兴。
代码看起来像:
sed -i "/TEXT_TO_BE_REPLACED/c $REPLACEMENT_TEXT_STRING" /tmp/foo
注意使用双引号而不是单引号。
接受的答案对我不起作用,原因如下:
-i
零长度扩展c\
命令的语法很奇怪,我无法让它工作所以这是我想出的解决方案,我认为它应该适用于大多数情况:
function escape_slashes {
sed 's/\//\\\//g'
}
function change_line {
local OLD_LINE_PATTERN=$1; shift
local NEW_LINE=$1; shift
local FILE=$1
local NEW=$(echo "${NEW_LINE}" | escape_slashes)
# FIX: No space after the option i.
sed -i.bak '/'"${OLD_LINE_PATTERN}"'/s/.*/'"${NEW}"'/' "${FILE}"
mv "${FILE}.bak" /tmp/
}
因此,解决问题的示例用法如下:
change_line "TEXT_TO_BE_REPLACED" "This line is removed by the admin." yourFile
到目前为止提供的所有答案都假设您对要替换的文本有所了解,这是有道理的,因为这就是 OP 所要求的。我提供的答案假设您对要替换的文本一无所知,并且文件中可能有一个单独的行,其中包含您不想被替换的相同或相似内容。此外,我假设您知道要替换的行的行号。
以下示例演示了通过特定行号删除或更改文本:
# replace line 17 with some replacement text and make changes in file (-i switch)
# the "-i" switch indicates that we want to change the file. Leave it out if you'd
# just like to see the potential changes output to the terminal window.
# "17s" indicates that we're searching line 17
# ".*" indicates that we want to change the text of the entire line
# "REPLACEMENT-TEXT" is the new text to put on that line
# "PATH-TO-FILE" tells us what file to operate on
sed -i '17s/.*/REPLACEMENT-TEXT/' PATH-TO-FILE
# replace specific text on line 3
sed -i '3s/TEXT-TO-REPLACE/REPLACEMENT-TEXT/'
用于操作配置文件
我想出了这个受skensell answer启发的解决方案
configLine [searchPattern] [replaceLine] [filePath]
它会:
功能:
function configLine {
local OLD_LINE_PATTERN=$1; shift
local NEW_LINE=$1; shift
local FILE=$1
local NEW=$(echo "${NEW_LINE}" | sed 's/\//\\\//g')
touch "${FILE}"
sed -i '/'"${OLD_LINE_PATTERN}"'/{s/.*/'"${NEW}"'/;h};${x;/./{x;q100};x}' "${FILE}"
if [[ $? -ne 100 ]] && [[ ${NEW_LINE} != '' ]]
then
echo "${NEW_LINE}" >> "${FILE}"
fi
}
疯狂的退出状态魔法来自https://stackoverflow.com/a/12145797/1262663
在我的makefile中我使用这个:
@sed -i '/.*Revision:.*/c\'"`svn info -R main.cpp | awk '/^Rev/'`"'' README.md
PS:不要忘记-i实际上改变了文件中的文本......所以如果你定义为“修订”的模式会改变,你也会改变模式来替换。
示例输出:
由 John Doe 编写的 Abc 项目
修订:1190
因此,如果您设置模式“修订:1190”,显然与您将它们定义为“修订:”不同......
bash-4.1$ new_db_host="DB_HOSTNAME=good replaced with 122.334.567.90"
bash-4.1$
bash-4.1$ sed -i "/DB_HOST/c $new_db_host" test4sed
vim test4sed
'
'
'
DB_HOSTNAME=good replaced with 122.334.567.90
'
它工作正常
cat find_replace | while read pattern replacement ; do
sed -i "/${pattern}/c ${replacement}" file
done
find_replace 文件包含 2 列,c1 具有要匹配的模式,c2 具有替换,sed 循环替换包含变量 1 的模式之一的每一行
要做到这一点而不依赖任何 GNUisms,例如-i
没有参数或c
没有换行符:
sed '/TEXT_TO_BE_REPLACED/c\
This line is removed by the admin.
' infile > tmpfile && mv tmpfile infile
在这种(符合 POSIX 标准的)命令形式中
c\
text
text
可以由一行或多行组成,并且应该成为替换的一部分的换行符必须被转义:
c\
line1\
line2
s/x/y/
s/x/y/
模式空间被两行替换后的新 sed 命令在哪里
line1
line2
将包含指定字符串的整行替换为该行的内容
文本文件:
Row: 0 last_time_contacted=0, display_name=Mozart, _id=100, phonebook_bucket_alt=2
Row: 1 last_time_contacted=0, display_name=Bach, _id=101, phonebook_bucket_alt=2
单串:
$ sed 's/.* display_name=\([[:alpha:]]\+\).*/\1/'
output:
100
101
由空格分隔的多个字符串:
$ sed 's/.* display_name=\([[:alpha:]]\+\).* _id=\([[:digit:]]\+\).*/\1 \2/'
output:
Mozart 100
Bach 101
调整正则表达式以满足您的需求
[:alpha] 和 [:digit:] 是字符类和括号表达式
和上面的一样。。
sed 's/[A-Za-z0-9]*TEXT_TO_BE_REPLACED.[A-Za-z0-9]*/This line is removed by the admin./'
下面的命令对我有用。哪个正在使用变量
sed -i "/\<$E\>/c $D" "$B"
我经常使用正则表达式从文件中提取数据,我只是用它来替换文字\"
引号//
:-)
cat file.csv | egrep '^\"([0-9]{1,3}\.[0-9]{1,3}\.)' | sed s/\"//g | cut -d, -f1 > list.txt