0

I have a file called test.out with the below lines in:

-rw-rw----    1 informix informix    9117025 Jan 21 05:22 shop4_0_Log0000331875.Z
-rw-rw----    1 informix informix    8897981 Jan 21 05:24 shop4_0_Log0000331876.Z
-rw-rw----    1 informix informix    9325351 Jan 21 05:31 shop4_0_Log0000331877.Z
-rw-rw----    1 informix informix    9645109 Jan 21 05:34 shop4_0_Log0000331878.Z
-rw-rw----    1 informix informix    9950581 Jan 21 05:40 shop4_0_Log0000331879.Z
-rw-rw----    1 informix informix   10655940 Jan 21 05:59 shop4_0_Log0000331880.Z
-rw-rw----    1 informix informix   10832325 Jan 21 06:39 shop4_0_Log0000331881.Z
-rw-rw----    1 informix informix    8521443 Jan 21 07:42 shop4_0_Log0000331882.Z
-rw-rw----    1 informix informix   10283566 Jan 21 08:02 shop4_0_Log0000331883.Z
-rw-rw----    1 informix informix   10633957 Jan 21 08:51 shop4_0_Log0000331884.Z

I want to print all lines above grep value 331881 parameter:

My desired outcome must be like below:

-rw-rw----    1 informix informix    9117025 Jan 21 05:22 shop4_0_Log0000331875.Z
-rw-rw----    1 informix informix    8897981 Jan 21 05:24 shop4_0_Log0000331876.Z
-rw-rw----    1 informix informix    9325351 Jan 21 05:31 shop4_0_Log0000331877.Z
-rw-rw----    1 informix informix    9645109 Jan 21 05:34 shop4_0_Log0000331878.Z
-rw-rw----    1 informix informix    9950581 Jan 21 05:40 shop4_0_Log0000331879.Z
-rw-rw----    1 informix informix   10655940 Jan 21 05:59 shop4_0_Log0000331880.Z

Using the command below command I can specify how much lines above to print:

grep -n 331881 test.out | cut -d':' -f1 |  xargs  -n1 -I % awk "NR<=%+0 && NR>=%-1" test.out | sed '$d'

The above command will only print the specified amount of lines in this case 1 line, but I want to change the above to print all above the grepped line. I am struggling to find a solution to my problem or an easier way.

2

Assuming that you are located in the directory that holds the listed files, using zsh:

ls -ld shop4_0_Log<331882->.Z

The <331882-> is a zsh-specific glob that matches integers that are 331882 or larger.

With some other shell:

for name in shop4_0_Log*.Z; do
    number=${name#shop4_0_Log}
    number=${number%.Z}

    if [ "$number" -ge 331882 ]; then
        ls -ld "$name"
    fi
done

Here, we loop over the names that start with shop4_0_Log and end with .Z. For each such name, we pick out the integer part of the filename, and if it is 331882 or more we call ls -ld on the name.

If the leading zeros are causing the shell to interpret some of the numbers as octal (it doesn't in my tests), then use 10#$number in the test to force the number to be interpreted as a decimal integer (this is supported by ksh and bash and some other shells).

Neither of these two variations relies on the presence of a text file that contains some ls output.

Related:

1

I think you can just use awk directly:

awk '/331881/ { exit } 1' test.out

This will print all lines, but for a line matching 331881, quit.

1

Another good tool would be sed:

sed -n '/shop4_0_Log0000331881\.Z$/q;p' test.out
0

Try removing the and condition, remove the following code from your one liner:

&& NR>=%-1
0
j=`awk '/331881/{print NR}' file`

awk -v j="$j" '{a[++i]=$0}/331881/{for(x=NR-j;x<NR;x++)print a[x]}' file

output

-rw-rw----    1 informix informix    9117025 Jan 21 05:22 shop4_0_Log0000331875.Z
-rw-rw----    1 informix informix    8897981 Jan 21 05:24 shop4_0_Log0000331876.Z
-rw-rw----    1 informix informix    9325351 Jan 21 05:31 shop4_0_Log0000331877.Z
-rw-rw----    1 informix informix    9645109 Jan 21 05:34 shop4_0_Log0000331878.Z
-rw-rw----    1 informix informix    9950581 Jan 21 05:40 shop4_0_Log0000331879.Z
-rw-rw----    1 informix informix   10655940 Jan 21 05:59 shop4_0_Log0000331880.Z

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.