Захватите определенный текст с помощью sed и sort + input обратно в файл - PullRequest
0 голосов
/ 06 сентября 2018

Я хотел бы попросить помощи.

В настоящее время я создаю сценарий, в котором в качестве основы будет задан файл, полный форматированного текста, а затем введен и удален из этого текстового файла в соответствии с пользовательским вводом. Я бы вставил это в скрипт bash.

Я понял, как извлечь нужный файл из файла, используя это:

sed -n '/5.1.1"/,/|}/p' textfile.txt

5.1.1 - это расположение моего сервера в стойке, и я беру текст файла, пока он не найдет |}.

Это выводит что-то вроде:

|+  description = "5.1.1";
|-
|1: ~servername~ [4U];
|-
|5: servername [2U];
|-
|7: servername [2U];
|-
|9: servername [2U];
|-
|11: servername [2U];
|-
|15: servername [2U];
|-
|17: servername [2U];
|-
|19: servername [2U];
|-
|21: ~servername~ [2U];
|-
|23: servername [2U];
|-
|25: servername [2U];
|-
|29: servername [2U];
|-
|31: servername [2U];
|-
|33: servername [2U];
|-
|35: ~servername~ [2U];
|-
|37: ~servername";
|-
|39: servername;
|-
|41: switch;
|}

И так далее, и так далее до 5.1.15.

sed просто выбирает текст, который мне нужно изменить.

В моем понимании, как это сделать, можно взять текст, который я взял с помощью sed, вставить нужную мне строку, а затем отсортировать ее по числу во втором столбце и снова вставить измененный текст обратно в файл в в том же месте, однако я не знаю, как это реализовать.

Строка, которую я буду вводить, будет в том же формате, что и другие строки, и тогда я получу | - под ней.

Большое спасибо

Редактировать 1:

Желаемый результат будет таким:

У меня есть строка 16: имя_сервера; что я хотел бы ввести в этот файл в стойке 5.1.1.

Конечный результат взятия базы сверху будет:

|+  description = "5.1.1";
|-
|1: ~servername~ [4U];
|-
|5: servername [2U];
|-
|7: servername [2U];
|-
|9: servername [2U];
|-
|11: servername [2U];
|-
|15: servername [2U];
|-
|16: servername;
|-
|17: servername [2U];
|-
|19: servername [2U];
|-
|21: ~servername~ [2U];
|-
|23: servername [2U];
|-
|25: servername [2U];
|-
|29: servername [2U];
|-
|31: servername [2U];
|-
|33: servername [2U];
|-
|35: ~servername~ [2U];
|-
|37: ~servername";
|-
|39: servername;
|-
|41: switch;
|}

Редактировать 2:

Я решил включить сценарий, который написал для форматирования. Он неполон и довольно неопрятен, но он делает свое дело, кроме переменной if для переменной $ location. Для этого мне нужно переделать регулярное выражение.

#! /bin/bash


function serverread {

#Enter the location
function locationread { 
echo 'Enter the location of the server in the data center in format (x.x.x) ex. 5.1.15'
read location

if [[ "$location" =~ [0-9]{1,2}.[0-9]{1,2}.[0-9]{1,2} ]]
then
          echo "Success"
  else
            echo "You have entered an incorrect format for the rack, please try again."
            locationread
            exit
fi
}
locationread

echo Please enter the rack space at which the server was placed
read rp

if (( $rp < 1 || $rp > 42));
then
        echo You have entered an incorrect size for the server. Please enter a number between 1 and 42.
        read rp
else
{
        echo You entered: $rp as the server placement in the rack.
}
fi
#Enter the server name
echo Now please enter the server name "(Use ~ around the name if it is disconnected/unplugged)":
read name

if [[ $name == ~* ]] && [[ $name == *~ ]];
then
        echo "You entered: $name as the server name and it is currently disconnected in some way."
else
        echo "You entered: $name as the server name."
fi

#Enter the physical height of the server
echo Now please enter the size in height of the server:

function readsize {
read size
if [ $size -eq $size 2>/dev/null ]
then
        if (( $size < 1 || $size > 42));
        then
                echo You have entered an incorrect size for the server. Please enter a number between 1 and 42.
                readsize
        else
                echo "You entered: $size as the physical height of the server"
        fi
fi
}
readsize

#if (( $size == 1))
#
#  else
#                echo "$size is not an integer"
#        fi
#       
#if (( $size < 1 || $size > 42));
#then
#        echo You have entered an incorrect size for the server. Please enter a number between 1 and 42.
#        read size
#else
#        echo "You entered: $size as the physical height of the server"
#fi

if (( $size == 1));
then
        echo Currently this is the line that will be entered: $rp": "$name";"
else
        echo Currently this is the line that will be entered: $rp": "$name" ["$size"U];"
fi
echo Is this correct? '[yes/no]'
read matrix
echo Would you like to add another server? '[yes/no]'
read matrix2

if (( $matrix == "yes" ));
then
        if (( $matrix2 == "yes" ));
                then
                        serverread
        else
                        echo This is complete
                exit
        fi
else
        echo Please run this command again
        exit
fi
}
serverread

Редактировать 3:

Это то, для чего я изменил последнюю функцию, чтобы она соответствовала сценарию:

set finale="($rp": "$name" ["$size"U];""
echo Is this correct? '[yes/no]'
read matrix
echo Would you like to add another server? '[yes/no]'
read matrix2

if (( $matrix == "yes" ));
then
        {
        # all text before 5.1.1
        sed -n '/'"$location"'"/q;p;' racktext.txt;
        # parse text in this section
        sed -n '/'"$location"'"/,/|}/p' racktext.txt | input.sh
        # all text below this section
        sed -n '/'"$location"'"/{ :a; /|}/{ n; :b; p; n; bb; }; n; ba; };' racktext.txt
        # use sponge to overwrite the file in a pipeline
        } | sponge racktext.txt
        if (( $matrix2 == "yes" ));
                then
                        serverread
        else
                        echo This is complete
                exit
        fi
else
        echo Please run this command again
        exit
fi
}
serverread

И вот как я собирался сделать сценарий, который вы показали мне в отдельном файле:

#! /bin/bash

export $(cat rackformat | grep -v ^# | xargs)
echo $finale

while IFS= read -r l; do 
        if [[ "$l" =~ description ]]; then            
                msg="$l"$'\n';                 
        elif [[ "$l" =~ "}" ]]; then                    
                { 
                        echo -n "$msg" | grep -v '|-'; 
                        echo "\|$finale"; 
                } | sed 's/^|//' | sort -n | sed 's/^/|/' | while IFS= read -r l; do 
                echo "$l"; 
                echo '|-'; 
        done | head -n-1; 
        echo '|}'; 
else 
        msg+="$l"$'\n'; 
fi; 
done

Редактировать 4:

Я не включил вышеупомянутую часть, потому что я не думал, что она будет актуальной, однако, вероятно, я должен был включить ее, и это мое плохо. это текстовый файл перед вводом:

{| class="wikitable"
|
{| class="wikitable"
|+  description = "5.1.1";
|-
|1: ~servername~ [4U];
|-
|5: servername [2U];
|-
|7: servername [2U];
|-
|9: servername [2U];
|-
|11: servername [2U];
|-
|15: servername [2U];
|-
|17: servername [2U];
|-
|19: servername [2U];
|-
|21: ~servername~ [2U];
|-
|23: servername [2U];
|-
|25: servername [2U];
|-
|29: servername [2U];
|-
|31: servername [2U];
|-
|33: servername [2U];
|-
|35: ~servername~ [2U];
|-
|37: ~servername~;
|-
|39: servername;
|-
|41: servername;
|}
|
{| class="wikitable"

И это вывод текущего скрипта:

{| class="wikitable"
|
{| class="wikitable"
|\|2.: test [2U];
|-
|+  description = "5.1.1";
|-
|1: ~servername~ [4U];
|-
|5: servername [2U];
|-
|7: servername [2U];
|-
|9: servername [2U];
|-
|11: servername [2U];
|-
|15: servername [2U];
|-
|17: servername [2U];
|-
|19: servername [2U];
|-
|21: ~servername~ [2U];
|-
|23: servername [2U];
|-
|25: servername [2U];
|-
|29: servername [2U];
|-
|31: servername [2U];
|-
|33: servername [2U];
|-
|35: ~servername~ [2U];
|-
|37: ~servername~;
|-
|39: servername;
|-
|41: servername;
|}
|
{| class="wikitable"

А вот и весь текущий скрипт:

#! /bin/bash


function serverread {

#Enter the location
function locationread {
echo 'Enter the location of the server in the data center in format (x.x.x) ex. 5.1.15'
read location

if [[ "$location" =~ [0-9]{1,2}.[0-9]{1,2}.[0-9]{1,2} ]]
then
          echo "Success"
  else
            echo "You have entered an incorrect format for the rack, please try again."
            locationread
            exit
fi
}
locationread

function parser {
while IFS= read -r l; do 
        if [[ "$l" =~ description ]]; then            
                msg="$l"$'\n';                 
        elif [[ "$l" =~ "}" ]]; then                    
                { 
                        echo -n "$msg" | grep -v '|-'; 
                        echo "\|$finale"; 
                } | sed 's/^|//' | sort -n | sed 's/^/|/' | while IFS= read -r l; do 
                echo "$l"; 
                echo '|-'; 
        done | head -n-1; 
        echo '|}'; 
else 
        msg+="$l"$'\n'; 
fi; 
done
}

echo Please enter the rack space at which the server was placed
read rp

if (( $rp < 1 || $rp > 42));
then
        echo You have entered an incorrect size for the server. Please enter a number between 1 and 42.
        read rp
else
{
        echo You entered: $rp as the server placement in the rack.
}
fi
#Enter the server name
echo Now please enter the server name "(Use ~ around the name if it is disconnected/unplugged)":
read name

if [[ $name == ~* ]] && [[ $name == *~ ]];
then
        echo "You entered: $name as the server name and it is currently disconnected in some way."
else
        echo "You entered: $name as the server name."
fi

#Enter the physical height of the server
echo Now please enter the size in height of the server:

function readsize {
read size
if [ $size -eq $size 2>/dev/null ]
then
        if (( $size < 1 || $size > 42));
        then
                echo You have entered an incorrect size for the server. Please enter a number between 1 and 42.
                readsize
        else
                echo "You entered: $size as the physical height of the server"
        fi
fi
}
readsize

#if (( $size == 1))
#
#  else
#                echo "$size is not an integer"
#        fi
#       
#if (( $size < 1 || $size > 42));
#then
#        echo You have entered an incorrect size for the server. Please enter a number between 1 and 42.
#        read size
#else
#        echo "You entered: $size as the physical height of the server"
#fi

if (( $size == 1));
then
        echo Currently this is the line that will be entered: $rp": "$name";"
else
        echo Currently this is the line that will be entered: $rp": "$name" ["$size"U];"
fi

echo Is this correct? '[yes/no]'
read matrix
echo Would you like to add another server? '[yes/no]'
read matrix2

finale=$rp": "$name" ["$size"U];"
echo $finale

if (( $matrix == "yes" ));
then
        function b {
        # all text before 5.1.1
        sed -n '/'"$location"'"/q;p;' racktext.txt;
        # parse text in this section
        sed -n '/'"$location"'"/,/|}/p' racktext.txt | parser
        # all text below this section
        sed -n '/'"$location"'"/{ :a; /|}/{ n; :b; p; n; bb; }; n; ba; };' racktext.txt
        # use sponge to overwrite the file in a pipeline
        }
        b | sponge racktext.txt
        echo $
        if (( $matrix2 == "yes" ));
                then
                        serverread
        else
                        echo This is complete
        fi
else
        echo Please run this command again
        exit
fi
}
serverread

1 Ответ

0 голосов
/ 06 сентября 2018

Следующее script.sh работает для примера, переданного в stdin, как вы указали:

#!/bin/bash
while IFS= read -r l; do 
    if [[ "$l" =~ description ]]; then 
       msg="$l"$'\n'; 
    elif [[ "$l" =~ "}" ]]; then 
         { 
           echo -n "$msg" | grep -v '|-'; 
           echo '|16: servername;'; 
         } | sed 's/^|//' | sort -n | sed 's/^/|/' | while IFS= read -r l; do 
           echo "$l"; 
           echo '|-'; 
         done | head -n-1; 
         echo '|}'; 
     else 
         msg+="$l"$'\n'; 
     fi; 
done

Для следующего ввода:

|+  description = "5.1.1";
|-
|1: ~servername~ [4U];
|-
|5: servername [2U];
|-
|7: servername [2U];
|-
|9: servername [2U];
|-
|11: servername [2U];
|-
|15: servername [2U];
|-
|17: servername [2U];
|-
|19: servername [2U];
|-
|21: ~servername~ [2U];
|-
|23: servername [2U];
|-
|25: servername [2U];
|-
|29: servername [2U];
|-
|31: servername [2U];
|-
|33: servername [2U];
|-
|35: ~servername~ [2U];
|-
|37: ~servername";
|-
|39: servername;
|-
|41: switch;
|}

выводит следующее:

|+  description = "5.1.1";
|-
|1: ~servername~ [4U];
|-
|5: servername [2U];
|-
|7: servername [2U];
|-
|9: servername [2U];
|-
|11: servername [2U];
|-
|15: servername [2U];
|-
|16: servername;
|-
|17: servername [2U];
|-
|19: servername [2U];
|-
|21: ~servername~ [2U];
|-
|23: servername [2U];
|-
|25: servername [2U];
|-
|29: servername [2U];
|-
|31: servername [2U];
|-
|33: servername [2U];
|-
|35: ~servername~ [2U];
|-
|37: ~servername";
|-
|39: servername;
|-
|41: switch;
|}

Поскольку вы не предоставили ни описания формата этого файла, ни других примеров, я предположил:

  • строки |- можно игнорировать и удалять и никогда не изменится (сначала я думал, что это пустые тряпки, но потом они между 15 и 16 и 17, так что нет)
  • разделы начинаются с описания и заканчиваются |}

Вставить это обратно в скрипт вы можете:

{ 
     # all text before 5.1.1
     sed -n '/5.1.1"/q;p;' textfile.txt;
     # parse text in this section
     sed -n '/5.1.1"/,/|}/p' textfile.txt | script.sh
     # all text below this section
     sed -n '/5.1.1"/{ :a; /|}/{ n; :b; p; n; bb; }; n; ba; };' textfile.txt
 # use sponge to overwrite the file in a pipeline
 } | sponge textfile.txt
...