Is there a unix one liner to do this?
head -n 3 test.txt > out_dir/test.head.txt
grep hello test.txt > out_dir/test.tmp.txt
cat out_dir/test.head.txt out_dir/test.tmp.txt > out_dir/test.hello.txt
rm out_dir/test.head.txt out_dir/test.tmp.txt
I.e., I want to get the header and some grep lines from a given file, simultaneously.
Use awk:
awk 'NR<=3 || /hello/' test.txt > out_dir/test.hello.txt
You can say:
{ head -n 3 test.txt ; grep hello test.txt ; } > out_dir/test.hello.txt
Try using sed
sed -n '1,3p; /hello/p' test.txt > out_dir/test.hello.txt
The awk solution is the best, but I'll add a sed solution for completeness:
$ sed -n test.txt -e '1,3p' -e '4,$s/hello/hello/p' test.txt > $output_file
The -n says not to print out a line unless specified. The -e are the commands '1,3p prints ou the first three lines 4,$s/hello/hello/p looks for all lines that contain the word hello, and substitutes hello back in. The p on the end prints out all lines the substitution operated upon.
There should be a way of using 4,$g/HELLO/p, but I couldn't get it to work. It's been a long time since I really messed with sed.
Of course, I would go awk but here is an ed solution for the pre-vi nostalgics:
ed test.txt <<%
4,$ v/hello/d
w test.hello.txt
%
Related
I have following File (wishlist.txt):
Alligatoah Musik_ist_keine_lösung;https:///uhfhf
Alligatoah STRW;https:///uhfhf?i
Amewu Entwicklungshilfe;https:///uhfhf?i
and want to have the first word of line n.
so for n = 1:
Alligatoah
What i have so far is:
sed -e 's/\s.*//g' wishlist.txt
is there a elegant way to get rid of all lines except n?
Edit:
How to pass a bash variable "$i" to sed since
sed -n '$is/ .*//p' $wishlist
and
sed -n "\`${i}\`s/ .*//p" $wishlist
doesn't work
A couple of other techniques to get the first word of the 3rd line:
awk -v line=3 'NR == line {print $1; exit}' file
or
head -n 3 file | tail -n 1 | cut -d ' ' -f 1
Something like this. For the 1st word of the 3rd line.
sed -n '3s/\s.*//p' wishlist.txt
To use a variable: Note: Double quotes.
line=3; sed -n "${line}s/\s.*//p" wishlist.txt
sed supports "addresses", so you can tell it what lines to operate on. To print only the first line, you can use
sed -e '1!d; s/\s.*//'
where 1!d means: on lines other then 1, delete the line.
I want to get only one word from this txt file: http://pastebin.com/jFDu0Le5 . The word is from last row: WER: 45.67% Correct: 65.87% Acc: 54.33%
I want to get only the value: 45.67 to save it to the file value.txt..I want to create BASH script to get this value. Can you give me an example how to do it??? I am new in Bash and I need it for school. The whole .txt file is saved on my server as text file file.txt.
Try this:
grep WER file.txt | awk '{print $2}' | uniq | sed -e 's/%//' > value.txt
Note that this will overwrite value.txt each time you run the command.
You want grep "WER:" value.txt | cut -???
I have ??? because I do not know the structure of the file. Tab delimited? Fixed Width?
Do man cut an you can get the arguments you need.
There a many ways and instruments to do the task:
sed
tac file.txt | sed -n '/^WER: /{s///;s/%.*//;p;q}' > value.txt
awk
tac file.txt | awk -F'[ %]' '/^WER:/{print $2;exit}' > value.txt
bash
while read a b c
do
if [ $a = "WER:" ]
then
b=${b%\%*}
echo ${b#* }
break
fi
done < <(tac file.txt) > value.txt
If the format is as you said, then this also works
awk -F'[: %]' '/^WER/{print $3}' file.txt > value.txt
Explanation
-F specifies the field separator as one of [: %]
/<PATTERN>/ {<ACTION>} refers to: if a line matches some PATTERN, then do some ACTION
in my case,
the PATTERN is: starts with ^ the string WER
the ACTION is: print field $3 (as split by the -F field separators)
> sends the output to value.txt
if I have a file test.txt:
example 1 content 2013-3-8:
hello java
example 2 content 2013-4-9:
hello c
how can I use awk or sed to seperate the test.txt to two file
test1
hello java
test2
hello c
I use the command below:
awk '/example/{i++}{print > "test"i}' test.txt
but it will remain the first line(example xxx), can I add some fragment to the print in awk to delete the first line?
You almost have it:
awk '/^example/ { i++; next } { print >"test"i}'
the next makes awk skip the rest of the statements.
You can use getline to skip the first line. The following should give the desired output:
awk '/example/{getline; i++}{print > "test"i}' test.txt
Some weird way of doing this with sed:
sh <<< $(sed '/example/{N;s/\n//;s/example \([0-9]*\).*:\(.*\)/echo "\2" >> test\1;/}' input)
This might work for you (GNU sed):
sed -ne '2~4w test1.txt' -e '4~4w test2.txt' test0.txt
You could try something like :
awk 'BEGIN {i=0; j=0} /example/{i++; j=0} (j != 0){print > "test"i} {j++}' test.txt
sed -n "
/example 1/ {N;s/^.*\n//
w test1.txt
}
/example 2/ {N;s/^.*\n//
w test2.txt
}" test.txt
if you define a delimiter between section (define size or marker), there could be more text to put in each file
To complete the response from Alok Singhal: if you reach the "too many open files" limit on linux, you have to close the files in line.
awk '/^example/ {close("test" i); i++; next } { print >"test" i}'
I'm trying to insert a file content before a given pattern
Here is my code:
sed -i "" "/pattern/ {
i\\
r $scriptPath/adapters/default/permissions.xml"
}" "$manifestFile"
It adds the path instead of the content of the file.
Any ideas ?
In order to insert text before a pattern, you need to swap the pattern space into the hold space before reading in the file. For example:
sed "/pattern/ {
h
r $scriptPath/adapters/default/permissions.xml
g
N
}" "$manifestFile"
Just remove i\\.
Example:
$ cat 1.txt
abc
pattern
def
$ echo hello > 2.txt
$ sed -i '/pattern/r 2.txt' 1.txt
$ cat 1.txt
abc
pattern
hello
def
I tried Todd's answer and it works great,
but I found "h" & "g" commands are ommitable.
Thanks to this faq (found from #vscharf's comments), Todd's answer can be this one liner.
sed -i -e "/pattern/ {r $file" -e 'N}' $manifestFile
Edit:
If you need here-doc version, please check this.
I got something like this using awk. Looks ugly but did the trick in my test:
command:
cat test.txt | awk '
/pattern/ {
line = $0;
while ((getline < "insert.txt") > 0) {print};
print line;
next
}
{print}'
test.txt:
$ cat test.txt
some stuff
pattern
some other stuff
insert.txt:
$ cat insert.txt
this is inserted file
this is inserted file
output:
some stuff
this is inserted file
this is inserted file
pattern
some other stuff
CodeGnome's solution don't work, if the pattern is on the last line..
So I used 3 commands.
sed -i '/pattern/ i\
INSERTION_MARKER
' $manifestFile
sed -i '/INSERTION_MARKER/r $scriptPath/adapters/default/permissions.xml' $manifestFile
sed -i 's/INSERTION_MARKER//' $manifestFile
I have two text files, I want to place a text in the middle of another, I did some research and found information about adding single strings:
I have a comment in the second text file called STUFFGOESHERE, so I tried:
sed '/^STUFFGOESHERE/a file1.txt' file2.txt
sed: 1: "/^STUFFGOESHERE/a long.txt": command a expects \ followed by text
So I tried something different, trying to place the contents of the text based on a given line, but no luck.
Any ideas?
This should do it:
sed '/STUFFGOESHERE/ r file1.txt' file2.txt
If you want to remove the STUFFGOESHERE line:
sed -e '/STUFFGOESHERE/ r file1.txt' -e '/STUFFGOESHERE/d' file2.txt
If you want to modify file2 in place:
sed -i -e...
(or maybe sed -i '' -e..., I'm using GNU sed 4.1.5.)
If you can use ex or ed, try
cat <<EOF | ex -e - file2.txt
/^STUFFGOESHERE/
.r file1.txt
w
q
EOF
The same script works for ed:
cat <<EOF | ed file2.txt
/^STUFFGOESHERE/
.r file1.txt
w
q
EOF
awk '/STUFFGOESHERE/{while((getline line<"file1")>0){ print line};next}1' file2
From a Unix shell (bash, csh, zsh, whatever):
: | perl -e '#c = join("", map {<>} 0..eof); print $c[0] =~ /STUFFGOESHERE/ ? $` . $c[1] . $'"'"' : $c[0]' file2.txt file1.txt > newfile2.txt