linux awk命令详解
简介
awk是一个强大的文本分析工具,相对于grep的查找,sed的编辑,awk在其对数据分析并生成报告时,显得尤为强大。简单来说awk就是把文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分再进行各种分析处理。
awk有3个不同版本: awk、nawk和gawk,未作特别说明,一般指gawk,gawk 是 AWK 的 GNU 版本。
awk其名称得自于它的创始人 Alfred Aho 、Peter Weinberger 和 Brian Kernighan 姓氏的首个字母。实际上 AWK 的确拥有自己的语言: AWK 程序设计语言 , 三位创建者已将它正式定义为“样式扫描和处理语言”。它允许您创建简短的程序,这些程序读取输入文件、为数据排序、处理数据、对输入执行计算以及生成报表,还有无数其他的功能。
使用方法
awk '{pattern + action}' {filenames}
尽管操作可能会很复杂,但语法总是这样,其中 pattern 表示 AWK 在数据中查找的内容,而 action 是在找到匹配内容时所执行的一系列命令。花括号({})不需要在程序中始终出现,但它们用于根据特定的模式对一系列指令进行分组。 pattern就是要表示的正则表达式,用斜杠括起来。
awk语言的最基本功能是在文件或者字符串中基于指定规则浏览和抽取信息,awk抽取信息后,才能进行其他文本操作。完整的awk脚本通常用来格式化文本文件中的信息。
通常,awk是以文件的一行为处理单位的。awk每接收文件的一行,然后执行相应的命令,来处理文本。
调用awk
有三种方式调用awk
1.命令行方式 awk [-F field-separator] 'commands' input-file(s) 其中,commands 是真正awk命令,[-F域分隔符]是可选的。 input-file(s) 是待处理的文件。 在awk中,文件的每一行中,由域分隔符分开的每一项称为一个域。通常,在不指名-F域分隔符的情况下,默认的域分隔符是空格。 2.shell脚本方式 将所有的awk命令插入一个文件,并使awk程序可执行,然后awk命令解释器作为脚本的首行,一遍通过键入脚本名称来调用。 相当于shell脚本首行的:#!/bin/sh 可以换成:#!/bin/awk 3.将所有的awk命令插入一个单独文件,然后调用: awk -f awk-script-file input-file(s) 其中,-f选项加载awk-script-file中的awk脚本,input-file(s)跟上面的是一样的。
本章重点介绍命令行方式。
入门实例
假设last -n 5的输出如下
[root@www ~]# last -n 5 <==仅取出前五行 root pts/1 192.168.1.100 Tue Feb 10 11:21 still logged in root pts/1 192.168.1.100 Tue Feb 10 00:46 - 02:28 (01:41) root pts/1 192.168.1.100 Mon Feb 9 11:41 - 18:30 (06:48) dmtsai pts/1 192.168.1.100 Mon Feb 9 11:41 - 11:41 (00:00) root tty1 Fri Sep 5 14:09 - 14:10 (00:01)
如果只是显示最近登录的5个帐号
#last -n 5 | awk '{print $1}' root root root dmtsai root
awk工作流程是这样的:读入有'\n'换行符分割的一条记录,然后将记录按指定的域分隔符划分域,填充域,$0则表示所有域,$1表示第一个域,$n表示第n个域。默认域分隔符是"空白键" 或 "[tab]键",所以$1表示登录用户,$3表示登录用户ip,以此类推。
如果只是显示/etc/passwd的账户
#cat /etc/passwd |awk -F ':' '{print $1}' root daemon bin sys
这种是awk+action的示例,每行都会执行action{print $1}。
-F指定域分隔符为':'。
如果只是显示/etc/passwd的账户和账户对应的shell,而账户与shell之间以tab键分割
#cat /etc/passwd |awk -F ':' '{print $1"\t"$7}' root /bin/bash daemon /bin/sh bin /bin/sh sys /bin/sh
如果只是显示/etc/passwd的账户和账户对应的shell,而账户与shell之间以逗号分割,而且在所有行添加列名name,shell,在最后一行添加"blue,/bin/nosh"。
cat /etc/passwd |awk -F ':' 'BEGIN {print "name,shell"} {print $1","$7} END {print "blue,/bin/nosh"}' name,shell root,/bin/bash daemon,/bin/sh bin,/bin/sh sys,/bin/sh .... blue,/bin/nosh
awk工作流程是这样的:先执行BEGING,然后读取文件,读入有/n换行符分割的一条记录,然后将记录按指定的域分隔符划分域,填充域,$0则表示所有域,$1表示第一个域,$n表示第n个域,随后开始执行模式所对应的动作action。接着开始读入第二条记录······直到所有的记录都读完,最后执行END操作。
搜索/etc/passwd有root关键字的所有行
#awk -F: '/root/' /etc/passwd root:x:0:0:root:/root:/bin/bash
这种是pattern的使用示例,匹配了pattern(这里是root)的行才会执行action(没有指定action,默认输出每行的内容)。
搜索支持正则,例如找root开头的: awk -F: '/^root/' /etc/passwd
搜索/etc/passwd有root关键字的所有行,并显示对应的shell
# awk -F: '/root/{print $7}' /etc/passwd /bin/bash
这里指定了action{print $7}
awk内置变量
awk有许多内置变量用来设置环境信息,这些变量可以被改变,下面给出了最常用的一些变量。
ARGC 命令行参数个数 ARGV 命令行参数排列 ENVIRON 支持队列中系统环境变量的使用 FILENAME awk浏览的文件名 FNR 浏览文件的记录数 FS 设置输入域分隔符,等价于命令行 -F选项 NF 浏览记录的域的个数 NR 已读的记录数 OFS 输出域分隔符 ORS 输出记录分隔符 RS 控制记录分隔符
此外,$0变量是指整条记录。$1表示当前行的第一个域,$2表示当前行的第二个域,......以此类推。
统计/etc/passwd:文件名,每行的行号,每行的列数,对应的完整行内容:
#awk -F ':' '{print "filename:" FILENAME ",linenumber:" NR ",columns:" NF ",linecontent:"$0}' /etc/passwd filename:/etc/passwd,linenumber:1,columns:7,linecontent:root:x:0:0:root:/root:/bin/bash filename:/etc/passwd,linenumber:2,columns:7,linecontent:daemon:x:1:1:daemon:/usr/sbin:/bin/sh filename:/etc/passwd,linenumber:3,columns:7,linecontent:bin:x:2:2:bin:/bin:/bin/sh filename:/etc/passwd,linenumber:4,columns:7,linecontent:sys:x:3:3:sys:/dev:/bin/sh
使用printf替代print,可以让代码更加简洁,易读
awk -F ':' '{printf("filename:%10s,linenumber:%s,columns:%s,linecontent:%s\n",FILENAME,NR,NF,$0)}' /etc/passwd
print和printf
awk中同时提供了print和printf两种打印输出的函数。
其中print函数的参数可以是变量、数值或者字符串。字符串必须用双引号引用,参数用逗号分隔。如果没有逗号,参数就串联在一起而无法区分。这里,逗号的作用与输出文件的分隔符的作用是一样的,只是后者是空格而已。
printf函数,其用法和c语言中printf基本相似,可以格式化字符串,输出复杂时,printf更加好用,代码更易懂。
awk编程
变量和赋值
除了awk的内置变量,awk还可以自定义变量。
下面统计/etc/passwd的账户人数
awk '{count++;print $0;} END{print "user count is ", count}' /etc/passwd root:x:0:0:root:/root:/bin/bash ...... user count is 40
count是自定义变量。之前的action{}里都是只有一个print,其实print只是一个语句,而action{}可以有多个语句,以;号隔开。
这里没有初始化count,虽然默认是0,但是妥当的做法还是初始化为0:
awk 'BEGIN {count=0;print "[start]user count is ", count} {count=count+1;print $0;} END{print "[end]user count is ", count}' /etc/passwd [start]user count is 0 root:x:0:0:root:/root:/bin/bash ... [end]user count is 40
统计某个文件夹下的文件占用的字节数
ls -l |awk 'BEGIN {size=0;} {size=size+$5;} END{print "[end]size is ", size}' [end]size is 8657198
如果以M为单位显示:
ls -l |awk 'BEGIN {size=0;} {size=size+$5;} END{print "[end]size is ", size/1024/1024,"M"}' [end]size is 8.25889 M
注意,统计不包括文件夹的子目录。
条件语句
awk中的条件语句是从C语言中借鉴来的,见如下声明方式:
if (expression) { statement; statement; ... ... } if (expression) { statement; } else { statement2; } if (expression) { statement1; } else if (expression1) { statement2; } else { statement3; }
统计某个文件夹下的文件占用的字节数,过滤4096大小的文件(一般都是文件夹):
ls -l |awk 'BEGIN {size=0;print "[start]size is ", size} {if($5!=4096){size=size+$5;}} END{print "[end]size is ", size/1024/1024,"M"}' [end]size is 8.22339 M
循环语句
awk中的循环语句同样借鉴于C语言,支持while、do/while、for、break、continue,这些关键字的语义和C语言中的语义完全相同。
数组
因为awk中数组的下标可以是数字和字母,数组的下标通常被称为关键字(key)。值和关键字都存储在内部的一张针对key/value应用hash的表格里。由于hash不是顺序存储,因此在显示数组内容时会发现,它们并不是按照你预料的顺序显示出来的。数组和变量一样,都是在使用时自动创建的,awk也同样会自动判断其存储的是数字还是字符串。一般而言,awk中的数组用来从记录中收集信息,可以用于计算总和、统计单词以及跟踪模板被匹配的次数等等。
显示/etc/passwd的账户
awk -F ':' 'BEGIN {count=0;} {name[count] = $1;count++;}; END{for (i = 0; i < NR; i++) print i, name[i]}' /etc/passwd 0 root 1 daemon 2 bin 3 sys 4 sync 5 games ......
这里使用for循环遍历数组
awk编程的内容极多,这里只罗列简单常用的用法,更多请参考 http://www.gnu.org/software/gawk/manual/gawk.html
Linux vim 随记
命令模式
三种命令模式
vim的三种命令模式:
- 命令模式:用于输入命令,简单更改
- 插入模式:用于插入文本,修改文本
- 末行模式:用于输入命令,视化操作,查找替换等
三种模式之间的切换方式:
- 命令模式进入到插入模式:输入文本插入命令(i,I,a,A,o,O)
- 插入模式退出到命令模式:ESC
- 命令模式进入到末行模式:冒号:
- 末行模式退出到命令模式:Enter或者ESC.
vim命令集合:http://www.cnblogs.com/kzloser/archive/2012/09/12/2681111.html
图释指令
光标移动-------------
按行移动:
按字符移动:
插入命令-------------
常用命令-------------
普通模式下命令
复制,删除,粘贴
- 粘贴: 把 vim 中缓存区的数据,粘贴到光标附近(即 p 为光标后, P为光标前)
- 删除: 把 vim 中选中的删除数据先拷贝到缓冲区并覆盖原有数据,然后删除选中数据
- 复制: 把 vim 中选中的数据拷贝的缓冲区并覆盖原有数据
例子:
现在有数据如下:aaaaabbbbbcccccdddddfffff
假设我们的光标在第一个 b 这个位置, 在一般模式下输入 5x (即输入删除 5 个 b 的操作) 后结果为:
aaaaacccccdddddfffff
然后在按下 p (即在光标位置处后面粘贴缓冲区的数据),结果为:
aaaaacbbbbbccccdddddfffff
删除某区域内容:
可以重复的:
[d]+[num]+[ h / j / k / l / w / b / e / ( / ) / { / } / $ / G / /word / ?word / tc / Tc / fc / Fc / `c ]
- d: 表示删除操作
- 重复操作次数: num 表示操作重复次数
- 操作区域选择:
- h 删除光标前一个字符
- l 删除光标所在处的字符
- j 删除本行与下一行
- k 删除本行与上一行
- w 删除光标开始到下一个单词词首处
- b 删除光标开始到上一个单词词首处
- e 删除光标开始到这个单词的结尾处
- ( 删除光标开始到句子结束处
- ) 删除光标开始到句子开始处
- { 删除光标开始到段落开始处
- } 删除光标开始到段落结束处
- $ 删除从光标开始处到行尾处
- G 删除从光标所在行到行尾处
- /word 删除从光标开始处到下个 word 字符串,不含 word ( word 指代任意字符串 )
- ?word 删除从光标开始处到上个 word 字符串,不含 word ( word 指代任意字符串 )
- tc 删除从光标开始处到下个 c 字符处,不含 c ( c 指代任意字符 )
- Tc 删除从光标开始处到上个 c 字符处,不含 c ( c 指代任意字符 )
- fc 删除从光标开始处到下个 c 字符处,含 c ( c 指代任意字符 )
- Fc 删除从光标开始处到上个 c 字符处,含 c ( c 指代任意字符 )
- `c 删除从光标开始到标记 c 这个位置
不可重复的:
[d]+[ 0 / ^ / H / L ]
- d: 表示删除操作
- 操作区域选择:
- d0 删除从光标所在处到某一行的开始位置
- d^ 删除到某一行的第一个字符位置(不包括空格或TAB字符)
- dL 删除直到屏幕上最后一行的内容
- dH 删除直到屏幕上第一行的内容
复制某区域内容:
可以重复的:
[y]+[num]+[ h / j / k / l / w / b / e / ( / ) / { / } / $ / G / /word / ?word / tc / Tc / fc / Fc / `c ]
含义用法如删除类似
不可重复的:
[y]+[ 0 / ^ / H / L ]
含义用法如删除类似
多加介绍个与上面用法相似的操作:
改变某区域内容:
可以重复的:
[c]+[num]+[ h / j / k / l / w / b / e / ( / ) / { / } / $ / G / /word / ?word / tc / Tc / fc / Fc / `c ]
含义用法如删除类似
不可重复的:
[c]+[ 0 / ^ / H / L ]
含义用法如删除类似
操作的组合
v 字符选择
操作流程:
v + 移动光标按键+ 数据操作键
- v 开始选择字符的标志
- 移动光标按键 移动光标确定选择区域(此处可以为多个移动光标的键值,但不能为组合键:如 [Ctrl]+[p] 等等)
- 数据操作键 对选择区域内的数据内容进行操作
例子[删除选择的字符区间 vwd(vwx)] :
现在有数据如下:
aaaaabbbbb ccccc
按下 v 键时(标志开始选择区域的操作):
aaaaa|bbbbb ccccc
按下 w 键时(选择操作区域,当然这里的 w 是可以换成 llllll [ 即六个小写的 L ]):
aaaaabbbbb ccccc
按下 d/x 键时(对数据进行操作,即删除所选择区域中的数据):
aaaaaccccc
V 列选择
操作流程:
V + 移动光标按键+ 数据操作键
- V 开始选择字符的标志
- 移动光标按键 移动光标确定选择区域(此处可以为多个移动光标的键值或者没有键值当没有键值的时候操作区域为光标所在行,但不能为组合键:如 [Ctrl]+[p] 等等)
- 数据操作键 对选择区域内的数据内容进行操作
例子[删除本行和下行数据 Vjd(Vjx)] :
现在有数据如下:
aaaaa
bbbbb
ccccc
按下 V 键时(标志开始选择区域的操作):
aaaaa
bbbbb
ccccc
按下 j 键时(选择操作区域):
aaaaa
bbbbb
ccccc
按下 d/x 键时(对数据进行操作,即删除所选择区域中的数据):
ccccc
字符串搜索
搜索字符串中的特殊字符
- ^ (行开始指示符)
当脱字符( 即 ^ ),作为搜索字符串的第一个字符时, vim 将每行的开始字符与搜索字符串进行匹配. - . (任意字符指示符)
句点( 即 . )可以与任意字符匹配,它可以出现在搜索字符串中的任意位置.当要查找句点符号时候可以用转义字符 . 来查找句点符号 - < (字符开始指示符)
这两个字符与单词的开始匹配 - > (字符结束指示符)
这两个字符与单词的结束匹配 - * (0个或者过个出现)
这个字符时一个修饰符,它与某个字符的 0 次或者多次出现相匹配 - [] (定义字符类)
单个字符匹配的区间(这里想要了解的更详细的话可以参考 正则表达式 )例如 ds[ab] 代表的是 dsa 与 dsb
示例------
句子:
being kind to yourself in everyday life is one of the best things you can do for yourself.
life will become lighter and your relationships will most likely improve
搜索字符串 | 描述 | 结果(以单词为单位) |
/you | 查找字符串 you 的下一次出现的位置 | yourself, you, yourself, your |
/<you> | 查找单词 you 的下一次出现的位置 | you |
/^be | 查找以 be 开始的下一行 | being ... |
/^[a-z][a-z] | 查找以两个字符开头开始的下一行 | being ... , life ... |
/<th | 查找以 th 开头的单词 | the thing |
/[a-m]e> | 查找以 [a-m]e 为结尾的单词 | life, the, life, become |
命令行的命令
字符替换
语法格式:
[range]s/{pattern}/{string}/[flag] [count]
格式说明:
- range 表示行数
- %表示所有行
- n1,n2 表示由 n1 行到 n2 行之间
- s 表示substitution,替换的意思
- pattern 表示被替换的字符串
- string 表示替换的字符串
- flag 表示标志,取值g,i,c等
- g 表示global,全部
- i 表示ignore,忽略大小写
- c 表示confirm,一个一个交互确认替换
- count 表示从当前行到接下来的第几行,表示范围
例子:
(1). 全部替换
参数g实现全部替换,否则只替换一个
:%s/{old-pattern}/new-text/g
(2). 行内替换
%代表所有行,去掉%表示当前行,只替换当前行
:s/{old-pattern}/new-text/g
(3). 指定行范围替换
对1到10行的结果替换
:1,10s/{old-pattern}/new-text/g
(4). 可视模式替换
如果你觉得数行数比较麻烦,可以使用可视模式,首先进入可视模式,然后选择行
列,最后输入:自动进入:'<,'>
后面加上s/{old-pattern}/new-text/g,则只替换选择区域的结果
:'<,'>s/{old-pattern}/new-text/g
(5). 整词替换,而不是部分匹配的单词
对单词匹配模式外包一个<和>
:s/<blog>/weibo/g //替换blog,但是cnblog,blogs则不会替换
(6). 多项替换
同时对多个匹配都替换成某一字符串
:%s/(good|nice)/awesome/g //good和nice都将被替换成awesome
(7). 确认式替换
参数c让替换进行交互请求,需要你选择y,n,a,l,q
选择说明:
- y 替换且跳转到下一个匹配结果
- n 不替换且跳转到下一个匹配结果
- a 替换所有并退出交互模式
- l 替换当前并退出交互模式
- q 退出交互模式
:s/{old-pattern}/new-text/gc
(8). 行首插入行号
把行首^替换成行号,可自定义具体形式
:%s/^/=line(".")/g
录制
这个其实很简单,但也是很强大的功能,作用是记录你的操作,并把操作过程记录起来.然后可以用 @@ 来调用出来你刚刚记录的操作集合,从而简化了复杂操作的过程
过程:
- q //标志开始录制
- x //x 是这个录制的寄存器,x 可以是其它字符
- 操作过程
- q //标志录制结束,现在dd这个操作被定义到了 @x 这个命令里了
图释:
解读大型网站系统架构的演化
前言
一个成熟的大型网站(如淘宝、京东等)的系统架构并不是开始设计就具备完整的高性能、高可用、安全等特性,它总是随着用户量的增加,业务功能的扩展逐渐演变完善的,在这个过程中,开发模式、技术架构、设计思想也发生了很大的变化,就连技术人员也从几个人发展到一个部门甚至一条产品线。所以成熟的系统架构是随业务扩展而完善出来的,并不是一蹴而就;不同业务特征的系统,会有各自的侧重点,例如淘宝,要解决海量的商品信息的搜索、下单、支付,例如腾讯,要解决数亿的用户实时消息传输,百度它要处理海量的搜索请求,他们都有各自的业务特性,系统架构也有所不同。尽管如此我们也可以从这些不同的网站背景下,找出其中共用的技术,这些技术和手段可以广泛运行在大型网站系统的架构中,下面就通过介绍大型网站系统的演化过程,来认识这些技术和手段。
一、最开始的网站架构
最初的架构,应用程序、数据库、文件都部署在一台服务器上,如图:
二、应用、数据、文件分离
随着业务的扩展,一台服务器已经不能满足性能需求,故将应用程序、数据库、文件各自部署在独立的服务器上,并且根据服务器的用途配置不同的硬件,达到最佳的性能效果。
三、利用缓存改善网站性能
在硬件优化性能的同时,同时也通过软件进行性能优化,在大部分的网站系统中,都会利用缓存技术改善系统的性能,使用缓存主要源于热点数据的存在,大部分网站访问都遵循28原则(即80%的访问请求,最终落在20%的数据上),所以我们可以对热点数据进行缓存,减少这些数据的访问路径,提高用户体验。
缓存实现常见的方式是本地缓存、分布式缓存。当然还有CDN、反向代理等,这个后面再讲。本地缓存,顾名思义是将数据缓存在应用服务器本地,可以存在内存中,也可以存在文件,OSCache就是常用的本地缓存组件。本地缓存的特点是速度快,但因为本地空间有限所以缓存数据量也有限。分布式缓存的特点是,可以缓存海量的数据,并且扩展非常容易,在门户类网站中常常被使用,速度按理没有本地缓存快,常用的分布式缓存是Membercache、Redis。
四、使用集群改善应用服务器性能
应用服务器作为网站的入口,会承担大量的请求,我们往往通过应用服务器集群来分担请求数。应用服务器前面部署负载均衡服务器调度用户请求,根据分发策略将请求分发到多个应用服务器节点。
常用的负载均衡技术硬件的有F5,价格比较贵,软件的有LVS、Nginx、HAProxy。LVS是四层负载均衡,根据目标地址和端口选择内部服务器,Nginx和HAProxy是七层负载均衡,可以根据报文内容选择内部服务器,因此LVS分发路径优于Nginx和HAProxy,性能要高些,而Nginx和HAProxy则更具配置性,如可以用来做动静分离(根据请求报文特征,选择静态资源服务器还是应用服务器)。
五、数据库读写分离和分库分表
随着用户量的增加,数据库成为最大的瓶颈,改善数据库性能常用的手段是进行读写分离以及分表,读写分离顾名思义就是将数据库分为读库和写库,通过主备功能实现数据同步。分库分表则分为水平切分和垂直切分,水平切换则是对一个数据库特大的表进行拆分,例如用户表。垂直切分则是根据业务不同来切换,如用户业务、商品业务相关的表放在不同的数据库中。
六、使用CDN和反向代理提高网站性能
假如我们的服务器都部署在成都的机房,对于四川的用户来说访问是较快的,而对于北京的用户访问是较慢的,这是由于四川和北京分别属于电信和联通的不同发达地区,北京用户访问需要通过互联路由器经过较长的路径才能访问到成都的服务器,返回路径也一样,所以数据传输时间比较长。对于这种情况,常常使用CDN解决,CDN将数据内容缓存到运营商的机房,用户访问时先从最近的运营商获取数据,这样大大减少了网络访问的路径。比较专业的CDN运营商有蓝汛、网宿。
而反向代理,则是部署在网站的机房,当用户请求达到时首先访问反向代理服务器,反向代理服务器将缓存的数据返回给用户,如果没有没有缓存数据才会继续走应用服务器获取,也减少了获取数据的成本。反向代理有Squid,Nginx。
七、使用分布式文件系统
用户一天天增加,业务量越来越大,产生的文件越来越多,单台的文件服务器已经不能满足需求。需要分布式的文件系统支撑。常用的分布式文件系统有NFS。
八、使用NoSql和搜索引擎
对于海量数据的查询,我们使用nosql数据库加上搜索引擎可以达到更好的性能。并不是所有的数据都要放在关系型数据中。常用的NOSQL有mongodb和redis,搜索引擎有lucene。
九、将应用服务器进行业务拆分
随着业务进一步扩展,应用程序变得非常臃肿,这时我们需要将应用程序进行业务拆分,如百度分为新闻、网页、图片等业务。每个业务应用负责相对独立的业务运作。业务之间通过消息进行通信或者同享数据库来实现。
十、搭建分布式服务
这时我们发现各个业务应用都会使用到一些基本的业务服务,例如用户服务、订单服务、支付服务、安全服务,这些服务是支撑各业务应用的基本要素。我们将这些服务抽取出来利用分部式服务框架搭建分布式服务。淘宝的Dubbo是一个不错的选择。
小结
大型网站的架构是根据业务需求不断完善的,根据不同的业务特征会做特定的设计和考虑,本文只是讲述一个常规大型网站会涉及的一些技术和手段。
百度地图插件安装参考
百度地图插件安装参考:http://developer.baidu.com/map/index.php?title=jspopular
http://developer.baidu.com/map/index.php?title=%E9%A6%96%E9%A1%B5
下方有相关插件模块
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> </head> <body> <div id="map-canvas" class=""style="width:715px;height:400px"></div> <script src="http://api.map.baidu.com/api?v=1.5&ak=3912c09d8490b8c5754aedc170955e21" type="text/javascript"></script> <script type="text/javascript"> var map = new BMap.Map("map-canvas"); map.enableScrollWheelZoom(); var point = new BMap.Point(117.180386, 39.084208); map.centerAndZoom(point, 15); //加入缩放控件; map.addControl(new BMap.NavigationControl()); //创建坐标点; var marker1 = new BMap.Marker(point); map.addOverlay(marker1); </script> </html>
php/mysql/jquery实现各系统流行的瀑布流显示方式,实现很简单的!!!!
大家在用这个东西的时候一定要计得有这么几个文件,一个是jquery.js 还有就是你自己数据库的密码。和相对应的图片才可以正常看到效果。下面就是这里所有的代码!!!
HTML文件:waterfall.html
1. [代码][PHP]代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
|
View Code <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" > <html xmlns= "http://www.w3.org/1999/xhtml" > <head> <meta http-equiv= "Content-Type" content= "text/html; charset=utf-8" /> <title>瀑布流-Derek</title> <script type= "text/javascript" language= "javascript" src= "jquery.js" ></script> <link type= "text/css" rel= "stylesheet" href= "waterfall.css" /> <script type= "text/javascript" language= "javascript" src= "waterfall.js" ></script> </head> <body> <ul id= "stage" > <li></li> <li></li> <li></li> <li></li> </ul> </body> </html> /* * Javascript文件:waterfall.js */ $( function (){ jsonajax(); }); //这里就要进行计算滚动条当前所在的位置了。如果滚动条离最底部还有100px的时候就要进行调用ajax加载数据 $(window).scroll( function (){ //此方法是在滚动条滚动时发生的函数 // 当滚动到最底部以上100像素时,加载新内容 var $doc_height , $s_top , $now_height ; $doc_height = $(document).height(); //这里是document的整个高度 $s_top = $(this).scrollTop(); //当前滚动条离最顶上多少高度 $now_height = $(this).height(); //这里的this 也是就是window对象 if (( $doc_height - $s_top - $now_height ) < 100) jsonajax(); }); //做一个ajax方法来请求data.php不断的获取数据 var $num = 0; function jsonajax(){ $.ajax({ url: 'data.php' , type: 'POST' , data: "num=" + $num ++, dataType: 'json' , success: function (json){ if (typeof json == 'object' ){ var neirou, $row ,iheight,temp_h; for ( var i=0,l=json.length;i<l;i++){ neirou = json[i]; //当前层数据 //找了高度最少的列做添加新内容 iheight = -1; $( "#stage li" ).each( function (){ //得到当前li的高度 temp_h = Number($(this).height()); if (iheight == -1 || iheight >temp_h){ iheight = temp_h; $row = $(this); //此时$row是li对象了 } }); $item = $( '<div><img src="' +neirou.img+ '" border="0" ><br/>' +neirou.title+ '</div>' ).hide(); $row .append( $item ); $item .fadeIn(); } } } }); } /* * CSS文件:waterfall.css */ body{text-align:center;} /*Download by http://www.codefans.net*/ #stage{ margin:0 auto; padding:0; width:880px; } #stage li{ margin:0; padding:0; list-style:none;float:left; width:220px;} #stage li div{ font-size:12px; padding:10px; color:#999999; text-align:left; } /* * php文件:data.php */ <?php $link = mysql_connect( "localhost" , "root" , "" ); $sql = "use waterfall" ; mysql_query( $sql , $link ); $sql = "set names utf8" ; mysql_query( $sql , $link ); $num = $_POST [ 'num' ] *10; if ( $_POST [ 'num' ] != 0) $num +1; $sql = "select img,title from content limit " . $num . ",10" ; $result = mysql_query( $sql , $link ); $temp_arr = array (); while ( $row = mysql_fetch_assoc( $result )){ $temp_arr [] = $row ; } $json_arr = array (); foreach ( $temp_arr as $k => $v ){ $json_arr [] = (object) $v ; } //print_r($json_arr); echo json_encode( $json_arr ); |