2
CPUNAME AGENT_1
  DESCRIPTION "MANAGER CPU"
  OS UNIX
  NODE xxxxxxxxx.xxx.xxx.cxx TCPADDR 31111
  DOMAIN MASTERDM
  FOR MAESTRO
    TYPE MANAGER
    IGNORE
    AUTOLINK ON
    BEHINDFIREWALL OFF
    FULLSTATUS ON
END


CPUNAME AGENT_2
  DESCRIPTION "MANAGER CPU"
  OS UNIX
  NODE xxxxxxxxx.xxx.xxx.cxx TCPADDR 31111
  TIMEZONE abc
  DOMAIN MASTERDM
  FOR MAESTRO
    TYPE MANAGER
    IGNORE
    AUTOLINK ON
    BEHINDFIREWALL OFF
    FULLSTATUS ON
END


CPUNAME AGENT_3
  DESCRIPTION "MANAGER CPU"
  OS UNIX
  NODE xxxxxxxxx.xxx.xxx.cxx TCPADDR 31111
    TYPE MANAGER
    IGNORE
    AUTOLINK ON
    BEHINDFIREWALL OFF
    FULLSTATUS ON
END


DOMAIN MASTERDM
  *MANAGER AGENT_1
  ISMASTER
END
  1. In the above file first I appended a line "IGNORE" after pattern match "TYPE".

    sed -i '/^    TYPE.*/a IGNORE' filename 
    
  2. I need to delete the IGNORE flag for the specific CPU, for example, AGENT_1 AGENT_3, but the position of IGNORE is not fixed as you can see above.  It's coming at 8th, 9th & 6th for different block.  As of now I know the CPUs for which I am editing the file IGNORE flag is at 8th so I used a for loop and remove the IGNORE.

    for s in `cat $INPUT_FILE | awk '{print $1}'`; do
            echo $s
            sed -i "/$s/!b;n;n;n;n;n;n;n;d" Filename
    done
    
  3. As I know the position of NODE is always fixed for all blocks, I used the below command to replace the line.

    for n in `cat $INPUT_FILE`; do
        CPU=$(echo $n | cut -f1)
        NODE=$(echo $n | cut -f2)
        echo "$CPU"
        echo "$NODE"
        sed -i "/$CPU/!b;n;n;n;c $NODE" filename
    done
    

All above is working fine except removing the IGNORE for specific CPUs if it not comes at fixed line.  Kindly provide your valuable suggestion to improve the solution.

6
  • 2
    Please edit your question to show the expected output. Also, if those 2 blocks of text are intended to be in a single input file, then show them in a single input file, not as 2 separate blocks.
    – Ed Morton
    Commented Sep 18, 2022 at 9:45
  • In your specific case, Instead of counting and replacing the fourth line starting from the SACVL1790_MDM pattern, don't you prefer to replace the the line based on a pattern such as NODE .* TCPADDR 31111? If you just replace the fourth line of the block, you might replace undesired line if this pattern is not the fourth line of the block. Unless your specific example is irrelevant, and you want to know in general how to replace the nth line of the first matching block.
    – aviro
    Commented Sep 19, 2022 at 10:36
  • After the edit, your question seems very different in the original. It's still not clear for me. Your script showing something different than your question. In the question you say you want to remove lines, but in your loops you're replacing them. So do you want to delete lines, or replace them? If it's the latter, what do you want to replace them with? Also, why do you insist of asking how to delete the nth line, if you know that the line you want to delete is not necessarily the nth line? You also have there $INPUT_FILE which I you don't explain the content of, and filename.
    – aviro
    Commented Sep 21, 2022 at 8:06
  • Please edit your question and show the input file and expected output. In number 1 you tell that you insert the IGNORE lines, in 2 you tell us that you want to remove one/some of these line. Please add a separate definition of your requirements. It is difficult when this is mixed with the explanation of your code. If the file with IGNORE lines added is the input for the scope of the question, then show the file with IGNORE as input and remove paragraph 1 as it is not relevant. Or show the original input and define the task as to insert the IGNORE line(s) at specific places.
    – Bodo
    Commented Sep 21, 2022 at 20:01
  • I also find this question unclear.  (1) Thank you for showing us data and commands that you’ve tried. But, in my opinion, you should start the question with a broad explanation of what you’re trying to accomplish. I believe that questions that start with data are hard to understand. And you force us to read all your individual steps and try to figure out what your objective is. Also, maybe show the original, input data (it looks like you’re showing us an intermediate step).  … (Cont’d) Commented Sep 21, 2022 at 20:06

2 Answers 2

1

Task: Remove IGNORE lines for specified CPU names

If you want to remove the IGNORE line for AGENT_1 and AGENT_3 you can use

awk '$1 == "CPUNAME" && ($2 == "AGENT_1" || $2 == "AGENT_3") { x=1 }
/^END$/ { x=0 }
x && /^ *IGNORE$/ { next }
1' inputfile

You can add or remove CPU names in the condition as necessary.

This will print the modified data to standard output. Generally, I don't recommend in-place editing because you might lose your data if anything goes wrong. If you really want to replace your input file with a tool that doesn't support in-place editing, you can always use something like

awk 'some script' inputfile > tempfile && mv tempfile inputfile

Explanation

  • $1 == "CPUNAME" && ($2 == "AGENT_1" || $2 == "AGENT_3") Condition matches if the first field is CPUNAME and the second field is one of the specifeid names.
  • { x=1 } set flag x to mark that we want to remove IGNORE in this block
  • /^END$/ { x=0 } If the whole line matches END clear flag x at end of block.
  • x && /^ *IGNORE$/ Condition that matches a line IGNORE with leading space only if flag x is set.
  • { next } Skip further processing of this line, i.e. don't print it.
  • 1 Is a true (=every line) condition without an action which defaults to print. (You could write it more verbose as { print }.)

With the example input from the question

CPUNAME AGENT_1
  DESCRIPTION "MANAGER CPU"
  OS UNIX
  NODE xxxxxxxxx.xxx.xxx.cxx TCPADDR 31111
  DOMAIN MASTERDM
  FOR MAESTRO
    TYPE MANAGER
    IGNORE
    AUTOLINK ON
    BEHINDFIREWALL OFF
    FULLSTATUS ON
END


CPUNAME AGENT_2
  DESCRIPTION "MANAGER CPU"
  OS UNIX
  NODE xxxxxxxxx.xxx.xxx.cxx TCPADDR 31111
  TIMEZONE abc
  DOMAIN MASTERDM
  FOR MAESTRO
    TYPE MANAGER
    IGNORE
    AUTOLINK ON
    BEHINDFIREWALL OFF
    FULLSTATUS ON
END


CPUNAME AGENT_3
  DESCRIPTION "MANAGER CPU"
  OS UNIX
  NODE xxxxxxxxx.xxx.xxx.cxx TCPADDR 31111
    TYPE MANAGER
    IGNORE
    AUTOLINK ON
    BEHINDFIREWALL OFF
    FULLSTATUS ON
END


DOMAIN MASTERDM
  *MANAGER AGENT_1
  ISMASTER
END

the output is

CPUNAME AGENT_1
  DESCRIPTION "MANAGER CPU"
  OS UNIX
  NODE xxxxxxxxx.xxx.xxx.cxx TCPADDR 31111
  DOMAIN MASTERDM
  FOR MAESTRO
    TYPE MANAGER
    AUTOLINK ON
    BEHINDFIREWALL OFF
    FULLSTATUS ON
END


CPUNAME AGENT_2
  DESCRIPTION "MANAGER CPU"
  OS UNIX
  NODE xxxxxxxxx.xxx.xxx.cxx TCPADDR 31111
  TIMEZONE abc
  DOMAIN MASTERDM
  FOR MAESTRO
    TYPE MANAGER
    IGNORE
    AUTOLINK ON
    BEHINDFIREWALL OFF
    FULLSTATUS ON
END


CPUNAME AGENT_3
  DESCRIPTION "MANAGER CPU"
  OS UNIX
  NODE xxxxxxxxx.xxx.xxx.cxx TCPADDR 31111
    TYPE MANAGER
    AUTOLINK ON
    BEHINDFIREWALL OFF
    FULLSTATUS ON
END


DOMAIN MASTERDM
  *MANAGER AGENT_1
  ISMASTER
END


Reverse task: Insert IGNORE lines

If the real input file is without IGNORE lines, you could also use a script that will insert these lines only in blocks that match (or don't match) specified CPU names after the TYPE line.

Example: Insert IGNORE in blocks that don't match any of AGENT_1 and AGENT_3

awk '$1 == "CPUNAME" && ($2 != "AGENT_1" && $2 != "AGENT_3") { x=1 }
/^END$/ { x=0 }
1
x && $1 == "TYPE" { print "    IGNORE" }' inputfile

Explanation: (only where it differs from the first script)

  • $1 == "CPUNAME" && ($2 != "AGENT_1" && $2 != "AGENT_3") 1st field CPUNAME and 2nd field is neither of the two names.
  • x && $1 == "TYPE" flag x is set and the first field is TYPE
  • { print " IGNORE" } print IGNORE line (after the TYPE line)

Example input with CPUs AGENT_1..AGENT_4 and no IGNORE lines:

CPUNAME AGENT_1
  DESCRIPTION "MANAGER CPU"
  OS UNIX
  NODE xxxxxxxxx.xxx.xxx.cxx TCPADDR 31111
  DOMAIN MASTERDM
  FOR MAESTRO
    TYPE MANAGER
    AUTOLINK ON
    BEHINDFIREWALL OFF
    FULLSTATUS ON
END


CPUNAME AGENT_2
  DESCRIPTION "MANAGER CPU"
  OS UNIX
  NODE xxxxxxxxx.xxx.xxx.cxx TCPADDR 31111
  TIMEZONE abc
  DOMAIN MASTERDM
  FOR MAESTRO
    TYPE MANAGER
    AUTOLINK ON
    BEHINDFIREWALL OFF
    FULLSTATUS ON
END


CPUNAME AGENT_3
  DESCRIPTION "MANAGER CPU"
  OS UNIX
  NODE xxxxxxxxx.xxx.xxx.cxx TCPADDR 31111
    TYPE MANAGER
    AUTOLINK ON
    BEHINDFIREWALL OFF
    FULLSTATUS ON
END


CPUNAME AGENT_4
  DESCRIPTION "MANAGER CPU"
  OS UNIX
  NODE xxxxxxxxx.xxx.xxx.cxx TCPADDR 31111
    TYPE MANAGER
    AUTOLINK ON
    BEHINDFIREWALL OFF
    FULLSTATUS ON
END


DOMAIN MASTERDM
  *MANAGER AGENT_1
  ISMASTER
END

Resulting output:

CPUNAME AGENT_1
  DESCRIPTION "MANAGER CPU"
  OS UNIX
  NODE xxxxxxxxx.xxx.xxx.cxx TCPADDR 31111
  DOMAIN MASTERDM
  FOR MAESTRO
    TYPE MANAGER
    AUTOLINK ON
    BEHINDFIREWALL OFF
    FULLSTATUS ON
END


CPUNAME AGENT_2
  DESCRIPTION "MANAGER CPU"
  OS UNIX
  NODE xxxxxxxxx.xxx.xxx.cxx TCPADDR 31111
  TIMEZONE abc
  DOMAIN MASTERDM
  FOR MAESTRO
    TYPE MANAGER
    IGNORE
    AUTOLINK ON
    BEHINDFIREWALL OFF
    FULLSTATUS ON
END


CPUNAME AGENT_3
  DESCRIPTION "MANAGER CPU"
  OS UNIX
  NODE xxxxxxxxx.xxx.xxx.cxx TCPADDR 31111
    TYPE MANAGER
    AUTOLINK ON
    BEHINDFIREWALL OFF
    FULLSTATUS ON
END


CPUNAME AGENT_4
  DESCRIPTION "MANAGER CPU"
  OS UNIX
  NODE xxxxxxxxx.xxx.xxx.cxx TCPADDR 31111
    TYPE MANAGER
    IGNORE
    AUTOLINK ON
    BEHINDFIREWALL OFF
    FULLSTATUS ON
END


DOMAIN MASTERDM
  *MANAGER AGENT_1
  ISMASTER
END
3
  • Thanks for you valuable input. One more query. using given command instead of remove "IGNORE" if I want to replace 4th line for specific ex:- Agent_1 and Agent_3 which start with NODE till some numerical value (NODE xxxxxxxxx.xxx.xxx.cxx TCPADDR 31111). What changes I need to make in command in below command awk '$1 == "CPUNAME" && ($2 == "AGENT_1" || $2 == "AGENT_3") { x=1 } /^END$/ { x=0 } x && /^ *IGNORE$/ { next } 1' inputfile
    – nitesh
    Commented Sep 30, 2022 at 4:45
  • also Revers action only printing IGNORE. awk '$1 == "CPUNAME" && ($2 != "AGENT_1" && $2 != "AGENT_3") { x=1 } /^END$/ { x=0 } 1 x && $1 == "TYPE" { print " IGNORE" }' inputfile
    – nitesh
    Commented Sep 30, 2022 at 9:59
  • @nitesh If I understand correct, this is a new requirement. It is difficult to answer questions in comments, and it is even difficult to understand what you need. Changing/extending this question after answers have been written is also not desirable. Please, write a new question with a link to this question or this answer. Show sufficient example input and expected output. If you add a comment here with the link to the new question I will get a notification. The gray word Share below the question or answer will give you a link which you can add to the other question or to a comment.
    – Bodo
    Commented Sep 30, 2022 at 10:26
1

Using Raku (formerly known as Perl_6)

~$ raku -e 'my @a = slurp.split("\n\n"); .subst("    IGNORE\n").put if .match(/AGENT_1 | AGENT_3/) for @a;'  file

Briefly, the code above uses the Raku Programming Language. The entire file is read in using slurp, and split on \n\n consecutive newlines to break into records, which are stored in an array, @a. Then if a record matches either of the desired AGENTs, the record is output, with the line " IGNORE\n" substituted with nothing (i.e. deleted).

https://raku.org

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .