Search code examples
bashshellsed

How to extract particular field space separately in shell script using sed command


Input File : Test.txt

-rw-r--r--  1 dev dev  93K Sep 18 05:37 Server-23091805496-2-AC.log
-rw-r--r--  1 dev dev  40K Sep 18 05:44 ServerM-23090331-5709-log.log
-rw-r--r--  1 dev dev 484K Sep 18 05:46 Server-280334-12570-log.log
-rw-r--r--  1 dev dev 235K Sep 18 05:47 Server-233405500-1-AC.log

Output in 1st File :

Sep 18 05:37 Server-23091805496-2-AC.log
Sep 18 05:44 ServerM-23090331-5709-log.log
Sep 18 05:46 Server-280334-12570-log.log
Sep 18 05:47 Server-233405500-1-AC.log

Output in 2nd File :

Server-23091805496-2-AC.log
ServerM-23090331-5709-log.log
Server-280334-12570-log.log
Server-233405500-1-AC.log

Tried Below : 1. sed 's/ /\n/g' Test.txt 2. ls -ltr | grep "Sep 18 08:" |sed -n '1p'|cut -d ' ' -f2


Solution

  • One answer could be:

    sed <input.txt -e 's/.*K //g;w file1.txt' -e 's/.* //g;' >file2.txt
    

    Or better:

    sed <input.txt -e '
       s/^\([^[:space:]]\+[[:space:]]\+\)\{5\}//;
       w file1.txt' -e '
       s/\([^[:space:]]\+[[:space:]]\+\)\{3\}//;' >file2.txt
    

    Where

    • sed is run only once, without any fork to other tool,

    • 1st removing everything until K in first proposal,

      removing non-spaces followed by spaces, repeated 5 times, in second proposal

    • then w write to file file1.txt

    • At this point, first script part end with second quote, then a second part of script start with -e sed argument (see stevesliva's comment for explanation about this.).

    • Removing everything until last space in first proposal,

      removing non-spaces followed by spaces, repeated 3 times, in second proposal

    • Then send sed's standard output to file2.txt

    If ls -l show date in some language like french printing day as 1st field, justified to 2 characters (%2d), to keep the day field justified in file1.txt, you could add a little 2 chars requirement in 1st sed command:

    ls -l /some/path | sed -e '
       s/^\([^[:space:]]\+[[:space:]]\+\)\{5\}\( [0-9] \|[0-9]\{2\} \|[A-Z]\)/\2/;
       w file1.txt' -e '
       s/^ \?\([^[:space:]]\+[[:space:]]\+\)\{3\}//;' >file2.txt
    

    So 1st field is either a space followed by a digit or two digits. (The add a potential space at begin of last replacement command).

    Note: In this, I've used redirection for input (<input.txt), but this is not a need. Please read my comment in answer to Mark Setchell's coment.