Как заменить всю строку в текстовом файле по номеру строки
У меня есть ситуация, когда я хочу, чтобы bash script заменил всю строку в файле.
Номер строки всегда один и тот же, поэтому это может быть жестко закодированная переменная.
Я не пытаюсь заменить некоторую подстроку в этой строке, я просто хочу полностью заменить эту строку новой строкой.
Существуют ли какие-либо методы bash для этого (или что-то простое, которое может быть выбрано в .sh script).
Ответы
Ответ 1
Не самое большое, но это должно работать:
sed -i 'Ns/.*/replacement-line/' file.txt
где N
следует заменить номером вашей целевой линии. Это заменяет строку в исходном файле. Чтобы сохранить измененный текст в другом файле, отпустите параметр -i
:
sed 'Ns/.*/replacement-line/' file.txt > new_file.txt
Ответ 2
Я действительно использовал этот script, чтобы заменить строку кода в файле cron на наших серверах UNIX на некоторое время назад. Мы выполнили его как обычную оболочку script и не имели проблем:
#Create temporary file with new line in place
cat /dir/file | sed -e "s/the_original_line/the_new_line/" > /dir/temp_file
#Copy the new file over the original file
mv /dir/temp_file /dir/file
Это не номер строки, но вы можете легко переключиться на систему на основе номера строки, поместив номер строки перед s/
и разместив вместо the_original_line
подстановочный знак.
Ответ 3
Предположим, вы хотите заменить строку 4 текстом "different". Вы можете использовать AWK так:
awk '{ if (NR == 4) print "different"; else print $0}' input_file.txt > output_file.txt
AWK считает, что входные данные являются "записями", разделенными на "поля". По умолчанию одна строка - одна запись. NR
- количество записей. $0
представляет текущую полную запись (в то время как $1
является первым полем из записи и т.д., по умолчанию поля являются словами из строки).
Итак, если текущий номер строки равен 4, напечатайте строку "different", но в противном случае напечатайте строку без изменений.
В AWK программный код, заключенный в { }
, запускается один раз на каждой входной записи.
Вам нужно процитировать программу AWK в одиночных кавычках, чтобы оболочка не пыталась интерпретировать такие вещи, как $0
.
EDIT: более короткая и более элегантная программа AWK от @chepner в комментариях ниже:
awk 'NR==4 {$0="different"} { print }' input_file.txt
Только для записи (т.е. строка) номер 4, замените всю запись строкой "другой". Затем для каждой входной записи распечатайте запись.
Ясно, что мои навыки AWK ржавы! Спасибо, @chepner.
EDIT: см. также более короткую версию от @Dennis Williamson:
awk 'NR==4 {$0="different"} 1' input_file.txt
Как это работает, объясняется в комментариях: 1
всегда оценивает значение true, поэтому всегда выполняется соответствующий блок кода. Но не существует связанного блока кода, что означает, что AWK выполняет свое действие по умолчанию только для печати всей строки. AWK предназначен для использования таких коротких программ.
Ответ 4
Данный тестовый файл (test.txt)
Lorem ipsum dolor sit amet,
consectetur adipiscing elit.
Duis eu diam non tortor laoreet
bibendum vitae et tellus.
следующая команда заменит первую строку на "текст новой строки"
$ sed '1 c\
> newline text' test.txt
Результат:
newline text
consectetur adipiscing elit.
Duis eu diam non tortor laoreet
bibendum vitae et tellus.
дополнительную информацию можно найти здесь
http://www.thegeekstuff.com/2009/11/unix-sed-tutorial-append-insert-replace-and-count-file-lines/
Ответ 5
в bash, замените N, M номерами строк и xxx yyy на то, что вы хотите
i=1
while read line;do
if((i==N));then
echo 'xxx'
elif((i==M));then
echo 'yyy'
else
echo "$line"
fi
((i++))
done < orig-file > new-file
ИЗМЕНИТЬ
Фактически в этом решении есть некоторые проблемы с символами "\ 0" "\ t" и "\"
"\ t", можно решить, поставив IFS = перед чтением:
"\", в конце строки с -r
IFS= read -r line
но для "\ 0" переменная усечена, в чистом bash нет решения:
Присвоить строку, содержащую нулевой символ (\ 0), переменной в Bash
Но в обычном текстовом файле нет нулевого символа \0
perl будет лучшим выбором
perl -ne 'if($.==N){print"xxx\n"}elsif($.==M){print"yyy\n"}else{print}' < orig-file > new-file
Ответ 6
Отличный ответ от Chepner.
Он работает для меня в bash Shell.
# To update/replace the new line string value with the exiting line of the file
MyFile=/tmp/ps_checkdb.flag
`sed -i "${index}s/.*/${newLine}/" $MyFile`
здесь
index
- Строка no
newLine
- новая строка строки, которую мы хотим заменить.
Аналогично ниже код используется для чтения определенной строки в файле. Это не повлияет на фактический файл.
LineString=`sed "$index!d" $MyFile`
здесь
!d
- удалит строки, отличные от строки $index
Таким образом, мы получим вывод в виде строки строки $index
в файле.
Ответ 7
# Replace the line of the given line number with the given replacement in the given file.
function replace-line-in-file() {
local file="$1"
local line_num="$2"
local replacement="$3"
# Escape backslash, forward slash and ampersand for use as a sed replacement.
replacement_escaped=$( echo "$replacement" | sed -e 's/[\/&]/\\&/g' )
sed -i "${line_num}s/.*/$replacement_escaped/" "$file"
}
Ответ 8
На mac я использовал
sed -i '' -e 's/text-on-line-to-be-changed.*/text-to-replace-the=whole-line/' file-name
Ответ 9
Вы можете даже передать параметры команде sed:
test.sh
#!/bin/bash
echo "-> start"
for i in $(seq 5); do
# passing parameters to sed
j=$(($i+3))
sed -i "${j}s/.*/replaced by '$i'!/" output.dat
done
echo "-> finished"
exit
orignial output.dat:
a
b
c
d
e
f
g
h
i
j
Выполнение./test.sh дает новый output.dat
a
b
c
replaced by '1'!
replaced by '2'!
replaced by '3'!
replaced by '4'!
replaced by '5'!
i
j