Як замінити рядок у 5-му рядку з декількох текстових файлів?


22

Я хочу замінити 5 рядок з декількох текстових файлів ( file1.txt, file2.txt, file3.txt, file4.txt ) рядком "Доброго ранку", використовуючи одну команду терміналу.

Всі текстові файли знаходяться на моєму ~/Desktop.

Примітка: Мій робочий стіл складається з 6 .txt файлів. Я хочу застосувати зміни лише до вищезгаданих 4 текстових файлів.

Відповіді:


40

Ось кілька підходів. Я використовую розширення дужок ( file{1..4}.txt), що означаєfile1.txt file2.txt file3.txt file4.txt

  1. Perl

    perl -i -pe 's/.*/ Good Morning / if $.==5' file{1..4}.txt

    Пояснення:

    • -i: викликає perlредагування файлів на місці, змінюючи вихідний файл.

      Якщо -iсупроводжується суфіксом розширення файлу, створюється резервна копія для кожного модифікованого файлу. Наприклад: -i.bakстворюється, file1.txt.bakякщо file1.txtпід час виконання змінюється.

    • -p: означає прочитати вхідний файл рядок за рядком, застосувати сценарій та роздрукувати його.

    • -e: дозволяє передавати скрипт з командного рядка.

    • s/.*/ Good Morning /: Це замінить текст у поточному рядку ( .*) на Добрий ранок.

    • $.- це спеціальна змінна Perl, яка містить номер поточного рядка вхідного файлу. Таким чином, s/foo/bar/ if $.==5, означає заміну fooз barтільки на 5 - й лінії.

  2. sed

    sed -i '5s/.*/ Good Morning /' file{1..4}.txt

    Пояснення:

    • -i: Як perl, отредагуйте файл на місці.

    За замовчуванням sedдрукує кожен рядок вхідного файлу. Засіб 5s/pattern/replacement/замінює візерунок із заміною на 5-му рядку.

  3. Awk

    for f in file{1..4}.txt; do 
        awk 'NR==5{$0=" Good Morning "}1;' "$f" > foobar && mv foobar "$f"; 
    done

    Пояснення:

    awkне має еквівалента -iпараметру¹, що означає, що нам потрібно створити тимчасовий файл ( foobar), який потім перейменований для заміни оригіналу. Цикл bash for f in file{1..4}.txt; do ... ; doneпросто проходить кожен з file{1..4}.txt, зберігаючи поточне ім'я файлу як $f. В awk, NRце номер поточного рядка та $0вміст поточного рядка. Отже, сценарій замінить рядок ( $0) на "Добрий ранок" лише на 5-му рядку. 1;призначено awkдля "друку рядка".

    ¹ Більш нові версії так, як показав Devnull у своїй відповіді .

  4. coreutils

    for f in file{1..4}.txt; do 
        (head -4 "$f"; echo " Good Morning "; tail -n +6 "$f") > foobar && 
        mv foobar "$f"; 
    done 

    Пояснення:

    Петля пояснюється в попередньому розділі.

    • head -4: надрукуйте перші 4 рядки

    • echo " Good Morning ": друк "Доброго ранку"

    • tail -n +6: надрукувати все з 6-го рядка до кінця файлу

    Дужки ( )навколо цих трьох команд дозволяють зафіксувати результат усіх трьох (так, перші 4 рядки, потім "Доброго ранку", потім решта рядків) та перенаправляйте їх у файл.


23

Ви можете використовувати sed:

sed '5s/^/Good morning /' file

буде додано Good morningу п'ятому рядку файлу.

Якщо ви хочете замінити вміст у рядку 5, скажіть:

sed '5s/.*/Good morning/' file

Якщо ви хочете зберегти зміни у файлі на місці, скористайтеся -iопцією:

sed -i '5s/.*/Good morning/' file

sedможе обробляти більше одного файлу одночасно. Ви можете просто додати більше імен файлів на кінець команди. Ви також можете використовувати розширення bash для відповідності певним файлам:

# manually specified
sed -i '5s/.*/Good morning/' file1.txt file2.txt file3.txt file4.txt

# wildcard: all files on the desktop
sed -i '5s/.*/Good morning/' ~/Desktop/*

# brace expansion: file1.txt, file2.txt, file3.txt, file4.txt
sed -i '5s/.*/Good morning/' file{1..4}.txt

Більше про розширення підтяжок ви можете прочитати тут .


Версії 4.1.0 і новіших версій GNU поставляються з розширенням, яке дозволяє редагувати на місці. Отже, ви можете сказати:

gawk -i inplace 'NR==5{$0="Good morning"}7' file

замінити рядок №5 у файлі на Good morning!


2

Я не бачив рішення python, ось ось це:

import sys
import os
def open_and_replace(filename):

    with open(filename) as read_file:
        temp = open("/tmp/temp.txt","w")
        for index,line in enumerate(read_file,1):
            if  index == 5:
                temp.write("NEW STRING\n")
            else:
                temp.write(line.strip() + "\n")
        temp.close()
    os.rename("/tmp/temp.txt",filename)

for file_name in sys.argv[1:]:
    open_and_replace(file_name)

Основна ідея полягає в тому, що для кожного файлу, що подається в командному рядку як аргумент, ми виписуємо тимчасовий файл і перераховуємо кожен рядок у вихідному файлі. Якщо індекс рядка дорівнює 5, виписуємо інший рядок. Решта - лише заміна старого файлу на темп-файл Demo:

$> ls
file1.txt  file2.txt  file3.txt
$> cat file1.txt                                                               
line 1
line 2
line 3
line 4
GOOD MORNING
line 6
$> python ~/replace_5th_line.py file1.txt file2.txt  file3.txt                 
$> cat file1.txt                                                               
line 1
line 2
line 3
line 4
NEW STRING
line 6
$> cat file2.txt                                                               
line 1
line 2
line 3
line 4
NEW STRING
line 6

Те ж саме можна досягти при розумінні списку. Нижче наводиться одноклапник того ж сценарію:

cat /etc/passwd | python -c 'import sys; print "\n".join(["CUSTOM"  if index == 5 else line.strip() for index,line in enumerate(sys.stdin,1)])'

або без cat

python -c 'import sys; print "\n".join(["CUSTOM"  if index == 5 else line.strip() for index,line in enumerate(sys.stdin,1)])' < /etc/passwd

Залишилося просто перенаправити вихід редагованого вмісту в інший файл > output.txt


1

Ви можете використовувати Vim в режимі Ex:

for b in 1 2 3 4
do
  ex -sc '5c|Good Morning' -cx file"$b".txt
done
  1. 5 виберіть 5-й рядок

  2. c замінити текст

  3. x напишіть, чи були внесені зміни (вони були) і закрийте


0

Далі йде сценарій bash, який завершує процес perl, запропонований у цій відповіді

Приклад:

/ tmp / це

console:
  enabled:false

Потім запустіть наступне:

$ search_and_replace_on_line_of_file.sh false true 2 /tmp/it

і файл тепер містить

/ tmp / це

console:
  enabled:true

search_and_replace_on_line_of_file.sh

function show_help()
{
  IT=$(CAT <<EOF

  usage: SEARCH REPLACE LINE_NUM FILE

  e.g. 

  false true 52 /tmp/it  -> replaces false with true on line 52 of file /tmp/it

  )
  echo "$IT"
  exit
}

if [ "$1" == "help" ]
then
  show_help
fi
if [ -z "$4" ]
then
  show_help
fi

SEARCH_FOR=$1
REPLACE_WITH=$2
LINE_NO=$3
FILE_NAME=$4
perl -i -pe "s/$SEARCH_FOR/$REPLACE_WITH/ if $.==$LINE_NO" $FILE_NAME 
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.