0

I have a file called file.txt on Linux, containing:

sqlplus -s insert into table;  
commit;  
!  
sqlplus -s insert into table;  
commit;  
!  
sqlplus -s insert into table;  
commit;  
!
  
.  
.   

I want to create multiple files as shown below:

File1.txt:-

sqlplus -s insert into table;  
commit;  
!   

File2.txt

sqlplus -s insert into table;  
commit;  
!   
4
  • 1
    So, how should the files be created? Why do your output examples have the same contents? Why only three lines? Please edit your question and explain what you need, tell us what logic we should use to figure this out. Also, show us what you have done so far so we don't waste your time or ours giving you solutions you have already tried.
    – terdon
    Commented Jul 28, 2022 at 11:42
  • i have edited question hope my requirement is clear to you
    – sam
    Commented Jul 28, 2022 at 11:53
  • 1
    Not really. You still haven't explained what you need. Don't just show the output, explain the logic of how we can get to the output from the input. Should we separate on every third line? Or should we look for the string sqlplus and then a line with just !? Or something else? We need to know how you want us to split.
    – terdon
    Commented Jul 28, 2022 at 11:58
  • your both logic will work 1. we can separate on every 3rd line or 2. get sqlplus ,,,,,, till "!" i just want to create multiple files with above logic
    – sam
    Commented Jul 28, 2022 at 12:05

4 Answers 4

2

Using awk

$ awk '/^sqlplus/ {close(sql);sql="file"++c".txt"} {print > sql}' input_file
$ head *
==> file1.txt <==
sqlplus -s insert into table;
commit;
!

==> file2.txt <==
sqlplus -s insert into table;
commit;
!

==> file3.txt <==
sqlplus -s insert into table;
commit;
!

.
.
0

Typical job for awk:

START_PATTERN='^sqlplus -s' END_PATTERN='^!$' awk '
  !file && $0 ~ ENVIRON["START_PATTERN"] {
    file = sprintf("file%03d.txt", ++n)
  }
  file {
    print > file
    if ($0 ~ ENVIRON["END_PATTERN"]) {
      file = ""
      close(file)
    }
  }' < your-file

That approach allows lines to match both start and end patterns (not possible in your case).

0

If it is enough to make one file for every three lines of the original input file, you can do (with GNU awk):

awk 'NR%3==1{a++} {print > "file"a".txt"}' file.txt 

Running this on your data produces:

$ ls file?.txt 
file1.txt  file2.txt  file3.txt
4
  • 1
    @EdMorton fair enough, I limited it to GNU awk. As for the too many files, that can be a problem yes, but given the dearth of information in the OP, I am just going to assume it isn't. :P
    – terdon
    Commented Jul 28, 2022 at 13:55
  • As long as you say its gawk-only that;s fine as gawk can handle any number of open files.
    – Ed Morton
    Commented Jul 28, 2022 at 13:55
  • Ah! So that is why I've never seen this problem myself despite a couple of decades using awk! I only ever use gawk.
    – terdon
    Commented Jul 28, 2022 at 13:56
  • Right, gawk behaves as you'd want in many undefined behavior and other situations such as the 2 I mentioned and setting FS to null. If you were using the default awk on MacOS or busybox or any awk that comes with Solaris, etc. you'd have a very different experience :-).
    – Ed Morton
    Commented Jul 28, 2022 at 13:58
0

A much simpler solution with csplit

csplit infile -z -f 'file' '/^sqlplus/' '{*}'


╰─ → $ cat file00
sqlplus -s insert into table;
commit;
!
╰─ → $ cat file01
sqlplus -s insert into table;
commit;
!
╰─ → $ cat file02
sqlplus -s insert into table;
commit;
!

-f is used to set a prefix and -z to suppress empty files.

You must log in to answer this question.

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